Fixed #1888 Casts for missing types, cast handling for script local classes

This commit is contained in:
Jindra Petřík
2022-12-01 15:25:23 +01:00
parent 913d8102be
commit 263b401efc
29 changed files with 291 additions and 139 deletions

View File

@@ -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<Integer, GraphTargetItem> 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 {

View File

@@ -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 {

View File

@@ -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<Boolean> isStatic = new Reference<>(false);
Reference<GraphTargetItem> type = new Reference<>(null);
Reference<GraphTargetItem> 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

View File

@@ -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;
}
}

View File

@@ -55,8 +55,8 @@ public class GetLexIns extends InstructionDefinition {
GraphTargetItem obj,
int multinameIndex,
Reference<Boolean> isStatic, Reference<GraphTargetItem> type, Reference<GraphTargetItem> 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);

View File

@@ -147,8 +147,8 @@ public class GetPropertyIns extends InstructionDefinition {
GraphTargetItem obj,
FullMultinameAVM2Item multiname,
Reference<Boolean> isStatic, Reference<GraphTargetItem> type, Reference<GraphTargetItem> 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) {

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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<GraphTargetItem> 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);
}
}

View File

@@ -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());
}

View File

@@ -36,12 +36,15 @@ public class ConstructPropAVM2Item extends AVM2Item {
public GraphTargetItem propertyName;
public List<GraphTargetItem> args;
public GraphTargetItem type;
public ConstructPropAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem object, GraphTargetItem propertyName, List<GraphTargetItem> args) {
public ConstructPropAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem object, GraphTargetItem propertyName, List<GraphTargetItem> 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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<Integer> indices, List<String> names, List<String> namespaces, List<ABC> 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) {

View File

@@ -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<GraphTargetItem, ClassIndex> classes = new HashMap<>();
private final Map<ClassDef, ClassIndex> classes = new HashMap<>();
private final Map<PropertyDef, TraitIndex> instanceProperties = new HashMap<>();
@@ -343,23 +430,30 @@ public final class AbcIndexing {
private final Map<PropertyNsDef, TraitIndex> classNsProperties = new HashMap<>();
private final Map<PropertyNsDef, TraitIndex> scriptProperties = new HashMap<>();
public ClassIndex findClass(GraphTargetItem cls) {
if (!classes.containsKey(cls)) {
if (parent == null) {
return null;
}
return parent.findClass(cls);
private final Map<PropertyNsDef, TraitIndex> 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<GraphTargetItem> type, Reference<GraphTargetItem> 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<Integer> 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<GraphTargetItem> 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<GraphTargetItem> gti_keys = new HashSet<>(classes.keySet());
for (GraphTargetItem key : gti_keys) {
Set<ClassDef> 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<ClassIndex> 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!");

View File

@@ -104,41 +104,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item {
return abc.getSelectedAbc().constants.getNamespaceSetId(nssa, true);
}
private static GraphTargetItem multinameToType(Set<Integer> 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<GraphTargetItem> 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<Boolean> isType, Reference<GraphTargetItem> objectType, Reference<GraphTargetItem> propertyType, Reference<Integer> propertyIndex, Reference<ValueKind> propertyValue, Reference<ABC> 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<>());

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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<GraphTargetItem> subtypes) {
public TypeItem(DottedChain fullTypeName, List<GraphTargetItem> 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;