diff --git a/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java b/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java index 0ec66db7d..336b175e5 100644 --- a/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java +++ b/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java @@ -50,6 +50,10 @@ public class SourceGeneratorLocalData implements Serializable { public List scopeStack = new ArrayList(); public boolean documentClass; public ScriptInfo currentScript; + + public String getFullClass(){ + return pkg==null||pkg.isEmpty()?currentClass:pkg+"."+currentClass; + } public SourceGeneratorLocalData(HashMap registerVars, Integer inFunction, Boolean inMethod, Integer forInLevel) { this.registerVars = registerVars; diff --git a/src/com/jpexs/decompiler/flash/abc/avm2/ConstantPool.java b/src/com/jpexs/decompiler/flash/abc/avm2/ConstantPool.java index 68ae3c0d1..04ce6447d 100644 --- a/src/com/jpexs/decompiler/flash/abc/avm2/ConstantPool.java +++ b/src/com/jpexs/decompiler/flash/abc/avm2/ConstantPool.java @@ -179,6 +179,17 @@ public class ConstantPool { public int getStringCount() { return constant_string.size(); } + + public int getNamespaceSubIndex(int namespaceId){ + Namespace ns = constant_namespace.get(namespaceId); + int index=0; + for (int n = 1; n < namespaceId; n++) { + if(constant_namespace.get(n).name_index == ns.name_index && constant_namespace.get(n).kind == ns.kind){ + index++; + } + } + return index; + } public int getNamespaceId(Namespace val, int index) { for (int n = 1; n < constant_namespace.size(); n++) { diff --git a/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushShortIns.java b/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushShortIns.java index bfb64cfb0..15ce37587 100644 --- a/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushShortIns.java +++ b/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushShortIns.java @@ -43,7 +43,7 @@ public class PushShortIns extends InstructionDefinition implements PushIntegerTy @Override public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap localRegs, Stack stack, java.util.Stack scopeStack, ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - stack.push(new IntegerValueAVM2Item(ins, Long.valueOf(ins.operands[0]))); + stack.push(new IntegerValueAVM2Item(ins, Long.valueOf((long)(short)ins.operands[0]))); } @Override diff --git a/src/com/jpexs/decompiler/flash/abc/avm2/model/IntegerValueAVM2Item.java b/src/com/jpexs/decompiler/flash/abc/avm2/model/IntegerValueAVM2Item.java index f8467e63d..6b46109b8 100644 --- a/src/com/jpexs/decompiler/flash/abc/avm2/model/IntegerValueAVM2Item.java +++ b/src/com/jpexs/decompiler/flash/abc/avm2/model/IntegerValueAVM2Item.java @@ -59,10 +59,10 @@ public class IntegerValueAVM2Item extends NumberValueAVM2Item { @Override public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { AVM2Instruction ins = null; - if (value >= 0 && value <= 255) { - ins = new AVM2Instruction(0, new PushByteIns(), new int[]{(int) (long) value}, new byte[0]); - } else if (value >= 0 && value <= 65535) { - ins = new AVM2Instruction(0, new PushShortIns(), new int[]{(int) (long) value}, new byte[0]); + if (value >= -128 && value <= 127) { + ins = new AVM2Instruction(0, new PushByteIns(), new int[]{(int)(long)value}, new byte[0]); + } else if (value >= -32768 && value <= 32767) { + ins = new AVM2Instruction(0, new PushShortIns(), new int[]{((int) (long) value) & 0xffff}, new byte[0]); } else { ins = new AVM2Instruction(0, new PushIntIns(), new int[]{((AVM2SourceGenerator) generator).abc.constants.getIntId(value, true)}, new byte[0]); } diff --git a/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java b/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java index cc76410d1..3c7c34e60 100644 --- a/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java +++ b/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java @@ -1170,13 +1170,15 @@ public class AVM2SourceGenerator implements SourceGenerator { } public void generateClass(List importedClasses,List sinitVariables, boolean staticNeedsActivation, List staticInit, List openedNamespaces, int namespace, int initScope, String pkg, ClassInfo classInfo, InstanceInfo instanceInfo, SourceGeneratorLocalData localData, boolean isInterface, String name, String superName, GraphTargetItem extendsVal, List implementsStr, GraphTargetItem constructor, List traitItems) throws ParseException, CompilationException { - localData.currentClass = pkg == null || pkg.isEmpty() ? name : pkg + "." + name; + localData.currentClass = name; localData.pkg = pkg; List ret = new ArrayList<>(); if (extendsVal == null && !isInterface) { extendsVal = new TypeItem("Object"); } ParsedSymbol s = null; + + instanceInfo.name_index = traitName(namespace, name); Trait[] it = generateTraitsPhase1(name, superName, false, localData, traitItems, instanceInfo.instance_traits); Trait[] st = generateTraitsPhase1(name, superName, true, localData, traitItems, classInfo.static_traits); @@ -1252,8 +1254,7 @@ public class AVM2SourceGenerator implements SourceGenerator { instanceInfo.interfaces = new int[implementsStr.size()]; for (int i = 0; i < implementsStr.size(); i++) { instanceInfo.interfaces[i] = superIntName(localData,implementsStr.get(i)); - } - instanceInfo.name_index = traitName(namespace, name); + } } @Override @@ -1395,7 +1396,7 @@ public class AVM2SourceGenerator implements SourceGenerator { if (an instanceof UnresolvedAVM2Item) { UnresolvedAVM2Item n = (UnresolvedAVM2Item) an; if (n.resolved == null) { - String fullClass = localData.currentClass == null ? null : (localData.pkg==null||pkg.isEmpty() ? localData.currentClass : localData.pkg + "." + localData.currentClass); + String fullClass = localData.getFullClass(); GraphTargetItem res = n.resolve(new TypeItem(fullClass), paramTypes, paramNames, abc, allABCs, callStack, subvariables); if (res instanceof AssignableAVM2Item) { subvariables.set(i, (AssignableAVM2Item) res); @@ -2069,7 +2070,7 @@ public class AVM2SourceGenerator implements SourceGenerator { mb.code.code.add(ins(new GetLocal0Ins())); mb.code.code.add(ins(new PushScopeIns())); - int traitScope = 1; + int traitScope = 2; Map initScopes = new HashMap<>(); @@ -2109,7 +2110,7 @@ public class AVM2SourceGenerator implements SourceGenerator { } mb.code.code.add(ins(new ReturnVoidIns())); - mb.autoFillStats(abc, localData.documentClass ? 1 : 0, false); + mb.autoFillStats(abc, 1, false); abc.addMethodBody(mb); si.init_index = mb.method_info; localData.pkg = null; //FIXME: pkg.packageName; @@ -2175,11 +2176,14 @@ public class AVM2SourceGenerator implements SourceGenerator { return a.equals(b); } - public static boolean searchPrototypeChain(boolean instanceOnly, List abcs, String pkg, String obj, String propertyName, Reference outName, Reference outNs, Reference outPropNs, Reference outPropNsKind, Reference outPropType, Reference outPropValue) { + public static boolean searchPrototypeChain(boolean instanceOnly, List abcs, String pkg, String obj, String propertyName, Reference outName, Reference outNs, Reference outPropNs, Reference outPropNsKind, Reference outPropNsIndex, Reference outPropType, Reference outPropValue) { for (ABC abc : abcs) { if (!instanceOnly) { for (ScriptInfo ii : abc.script_info) { + if(ii.deleted){ + continue; + } for (Trait t : ii.traits.traits) { if (eq(pkg,t.getName(abc).getNamespace(abc.constants).getName(abc.constants))) { if (propertyName.equals(t.getName(abc).getName(abc.constants, new ArrayList()))) { @@ -2187,6 +2191,7 @@ public class AVM2SourceGenerator implements SourceGenerator { outNs.setVal(pkg); outPropNs.setVal(t.getName(abc).getNamespace(abc.constants).getName(abc.constants)); outPropNsKind.setVal(t.getName(abc).getNamespace(abc.constants).kind); + outPropNsIndex.setVal(abc.constants.getNamespaceSubIndex(t.getName(abc).namespace_index)); outPropType.setVal(getTraitReturnType(abc, t)); if (t instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst) t; @@ -2200,6 +2205,9 @@ public class AVM2SourceGenerator implements SourceGenerator { } for (int i = 0; i < abc.instance_info.size(); i++) { InstanceInfo ii = abc.instance_info.get(i); + if(ii.deleted){ + continue; + } Multiname clsName = ii.getName(abc.constants); if (obj.equals(clsName.getName(abc.constants, new ArrayList()))) { if (eq(pkg,clsName.getNamespace(abc.constants).getName(abc.constants))) { @@ -2214,6 +2222,7 @@ public class AVM2SourceGenerator implements SourceGenerator { outNs.setVal(pkg); outPropNs.setVal(t.getName(abc).getNamespace(abc.constants).getName(abc.constants)); outPropNsKind.setVal(t.getName(abc).getNamespace(abc.constants).kind); + outPropNsIndex.setVal(abc.constants.getNamespaceSubIndex(t.getName(abc).namespace_index)); outPropType.setVal(getTraitReturnType(abc, t)); if (t instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst) t; @@ -2233,6 +2242,7 @@ public class AVM2SourceGenerator implements SourceGenerator { outNs.setVal(pkg); outPropNs.setVal(t.getName(abc).getNamespace(abc.constants).getName(abc.constants)); outPropNsKind.setVal(t.getName(abc).getNamespace(abc.constants).kind); + outPropNsIndex.setVal(abc.constants.getNamespaceSubIndex(t.getName(abc).namespace_index)); outPropType.setVal(getTraitReturnType(abc, t)); if (t instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst) t; @@ -2245,7 +2255,7 @@ public class AVM2SourceGenerator implements SourceGenerator { Multiname superName = abc.constants.constant_multiname.get(ii.super_index); if (superName != null) { - return searchPrototypeChain(instanceOnly, abcs, superName.getNamespace(abc.constants).getName(abc.constants), superName.getName(abc.constants, new ArrayList()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType, outPropValue); + return searchPrototypeChain(instanceOnly, abcs, superName.getNamespace(abc.constants).getName(abc.constants), superName.getName(abc.constants, new ArrayList()), propertyName, outName, outNs, outPropNs, outPropNsKind,outPropNsIndex, outPropType, outPropValue); } else { return false; } @@ -2314,8 +2324,8 @@ public class AVM2SourceGenerator implements SourceGenerator { @Override public List generate(SourceGeneratorLocalData localData, TypeItem item) throws CompilationException { - String currentFullClassName = localData.currentClass == null ? null : (localData.pkg.isEmpty() ? localData.currentClass : localData.pkg + "." + localData.currentClass); - + String currentFullClassName = localData.getFullClass(); + if (localData.documentClass && item.toString().equals(currentFullClassName)) { int slotId = 0; int c = abc.findClassByName(currentFullClassName); @@ -2340,7 +2350,7 @@ public class AVM2SourceGenerator implements SourceGenerator { if (item instanceof UnresolvedAVM2Item) { - String fullClass = localData.currentClass == null ? null : (localData.pkg==null ||localData.pkg.isEmpty() ? localData.currentClass : localData.pkg + "." + localData.currentClass); + String fullClass = localData.getFullClass(); item = ((UnresolvedAVM2Item) item).resolve(new TypeItem(fullClass), new ArrayList(), new ArrayList(), abc, allABCs, new ArrayList(), new ArrayList()); } if (item instanceof TypeItem) { @@ -2351,7 +2361,7 @@ public class AVM2SourceGenerator implements SourceGenerator { throw new CompilationException("Invalid type:"+item.getClass().getName(), 0/*??*/); } if (typeItem instanceof UnresolvedAVM2Item) { - String fullClass = localData.currentClass == null ? null : (localData.pkg==null || localData.pkg.isEmpty() ? localData.currentClass : localData.pkg + "." + localData.currentClass); + String fullClass = localData.getFullClass(); typeItem = ((UnresolvedAVM2Item) typeItem).resolve(new TypeItem(fullClass), new ArrayList(), new ArrayList(), abc, allABCs, new ArrayList(), new ArrayList()); } diff --git a/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java b/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java index 78d36d4f0..bcd454190 100644 --- a/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java +++ b/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java @@ -907,7 +907,7 @@ public class ActionScriptParser { }else{ publicNs = gpublicNs; } - + openedNamespaces.add(privateNs = abc.constants.addNamespace(new Namespace(Namespace.KIND_PRIVATE, 0))); //abc.constants.getStringId(fileName + "$", true) @@ -2374,5 +2374,5 @@ public class ActionScriptParser { } System.exit(0); } - + } diff --git a/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/CallAVM2Item.java b/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/CallAVM2Item.java index 410fa2baf..5ca3318b3 100644 --- a/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/CallAVM2Item.java +++ b/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/CallAVM2Item.java @@ -76,20 +76,18 @@ public class CallAVM2Item extends AVM2Item { allAbcs.addAll(g.allABCs); String cname; String pkgName = ""; - cname = localData.currentClass; - if (cname!=null && cname.contains(".")) { - pkgName = cname.substring(0, cname.lastIndexOf('.')); - cname = cname.substring(cname.lastIndexOf('.') + 1); - } + cname = localData.currentClass; + pkgName = localData.pkg; GraphTargetItem obj = null; Reference outName = new Reference<>(""); Reference outNs = new Reference<>(""); Reference outPropNs = new Reference<>(""); - Reference outPropNsKind = new Reference<>(1); + Reference outPropNsKind = new Reference<>(1); + Reference outPropNsIndex = new Reference<>(0); Reference outPropType = new Reference<>(null); Reference outPropValue = new Reference<>(null); - if (cname!=null && AVM2SourceGenerator.searchPrototypeChain(true, allAbcs, pkgName, cname, n.getVariableName(), outName, outNs, outPropNs, outPropNsKind, outPropType, outPropValue)) { - NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.currentClass), n.line, "this", null, false, n.openedNamespaces); + if (cname!=null && AVM2SourceGenerator.searchPrototypeChain(true, allAbcs, pkgName, cname, n.getVariableName(), outName, outNs, outPropNs, outPropNsKind,outPropNsIndex, outPropType, outPropValue)) { + NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), n.line, "this", null, false, n.openedNamespaces); nobj.setRegNumber(0); obj = nobj; } @@ -116,18 +114,16 @@ public class CallAVM2Item extends AVM2Item { String cname; String pkgName = ""; cname = localData.currentClass; - if (cname!=null && cname.contains(".")) { - pkgName = cname.substring(0, cname.lastIndexOf('.')); - cname = cname.substring(cname.lastIndexOf('.') + 1); - } + pkgName = localData.pkg; Reference outName = new Reference<>(""); Reference outNs = new Reference<>(""); Reference outPropNs = new Reference<>(""); - Reference outPropNsKind = new Reference<>(1); + Reference outPropNsKind = new Reference<>(1); + Reference outPropNsIndex = new Reference<>(0); Reference outPropType = new Reference<>(null); Reference outPropValue = new Reference<>(null); - if (cname!=null && AVM2SourceGenerator.searchPrototypeChain(true, allAbcs, pkgName, cname, prop.propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType, outPropValue) && (localData.currentClass.equals("".equals(outNs.getVal()) ? outName.getVal() : outNs.getVal() + "." + outName.getVal()))) { - NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.currentClass), 0, "this", null, false, new ArrayList()); + if (cname!=null && AVM2SourceGenerator.searchPrototypeChain(true, allAbcs, pkgName, cname, prop.propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue) && (localData.currentClass.equals("".equals(outNs.getVal()) ? outName.getVal() : outNs.getVal() + "." + outName.getVal()))) { + NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), 0, "this", null, false, new ArrayList()); nobj.setRegNumber(0); obj = nobj; } diff --git a/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java b/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java index e7ab05bed..a454f8fd5 100644 --- a/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java +++ b/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java @@ -115,6 +115,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { } public void resolve(SourceGeneratorLocalData localData, Reference objectType, Reference propertyType, Reference propertyIndex, Reference propertyValue) { + GraphTargetItem thisType = new TypeItem(localData.getFullClass()); GraphTargetItem objType = null; GraphTargetItem objSubType = null; ValueKind propValue = null; @@ -179,6 +180,64 @@ public class PropertyAVM2Item extends AssignableAVM2Item { } }*/ } + + GraphTargetItem ttype = objType; + if(ttype == null){ + ttype = thisType; + } + + + + { + List abcs = new ArrayList<>(); + abcs.add(abc); + abcs.addAll(otherABCs); + if (ttype.equals(new TypeItem("__AS3__.vec.Vector"))) { + switch ("" + objSubType) { + case "int": + ttype = new TypeItem("__AS3__.vec.Vector$int"); + break; + case "Number": + ttype = new TypeItem("__AS3__.vec.Vector$double"); + break; + case "uint": + ttype = new TypeItem("__AS3__.vec.Vector$uint"); + break; + default: + ttype = new TypeItem("__AS3__.vec.Vector$object"); + } + } + loopa: + for (ABC a : abcs) { + for (InstanceInfo ii : a.instance_info) { + if(ii.deleted){ + continue; + } + Multiname m = ii.getName(a.constants); + if (multinameToType(ii.name_index, a.constants).equals(ttype)) { + Reference outName = new Reference<>(""); + Reference outNs = new Reference<>(""); + Reference outPropNs = new Reference<>(""); + Reference outPropNsKind = new Reference<>(1); + Reference outPropNsIndex = new Reference<>(0); + Reference outPropType = new Reference<>(null); + Reference outPropValue = new Reference<>(null); + if (AVM2SourceGenerator.searchPrototypeChain(false, abcs, m.getNamespace(a.constants).getName(a.constants), m.getName(a.constants, new ArrayList()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue)) { + objType = new TypeItem("".equals(outNs.getVal()) ? outName.getVal() : outNs.getVal() + "." + outName.getVal()); + propType = outPropType.getVal(); + propIndex = abc.constants.getMultinameId(new Multiname(Multiname.QNAME, + abc.constants.getStringId(propertyName, true), + abc.constants.getNamespaceId(new Namespace(outPropNsKind.getVal(), abc.constants.getStringId(outPropNs.getVal(), true)), outPropNsIndex.getVal(), true), 0, 0, new ArrayList()), true + ); + propValue = outPropValue.getVal(); + + break loopa; + } + } + } + } + } + if (objType == null) { for (MethodBody b : callStack) { for (int i = 0; i < b.traits.traits.size(); i++) { @@ -213,6 +272,9 @@ public class PropertyAVM2Item extends AssignableAVM2Item { } if (name_index > 0) { for (int c = 0; c < abc.instance_info.size(); c++) { + if(abc.instance_info.get(c).deleted){ + continue; + } for (Trait t : abc.instance_info.get(c).instance_traits.traits) { if (t.name_index == name_index) { objType = multinameToType(abc.instance_info.get(c).name_index, abc.constants); @@ -240,7 +302,10 @@ public class PropertyAVM2Item extends AssignableAVM2Item { } for (ScriptInfo si : abc.script_info) { - for (Trait t : si.traits.traits) { + if(si.deleted){ + continue; + } + for (Trait t : si.traits.traits) { if (t.name_index == name_index) { objType = new TypeItem("Object"); propType = AVM2SourceGenerator.getTraitReturnType(abc, t); @@ -261,21 +326,26 @@ public class PropertyAVM2Item extends AssignableAVM2Item { loopabc: for (ABC a : otherABCs) { for (int h = 0; h < a.instance_info.size(); h++) { - InstanceInfo ii = a.instance_info.get(h); + InstanceInfo ii = a.instance_info.get(h); + if(ii.deleted){ + continue; + } Multiname n = a.constants.constant_multiname.get(ii.name_index); if (n.getNamespace(a.constants).kind == Namespace.KIND_PACKAGE && n.getNamespace(a.constants).getName(a.constants).equals(nsname)) { Reference outName = new Reference<>(""); Reference outNs = new Reference<>(""); Reference outPropNs = new Reference<>(""); Reference outPropNsKind = new Reference<>(1); + Reference outPropNsIndex = new Reference<>(0); Reference outPropType = new Reference<>(null); Reference outPropValue = new Reference<>(null); - if (propertyName != null && AVM2SourceGenerator.searchPrototypeChain(false, abcs, nsname, n.getName(a.constants, new ArrayList()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType, outPropValue)) { + + if (propertyName != null && AVM2SourceGenerator.searchPrototypeChain(false, abcs, nsname, n.getName(a.constants, new ArrayList()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue)) { objType = new TypeItem("".equals(outNs.getVal()) ? outName.getVal() : outNs.getVal() + "." + outName.getVal()); propType = outPropType.getVal(); propIndex = abc.constants.getMultinameId(new Multiname(Multiname.QNAME, abc.constants.getStringId(propertyName, true), - abc.constants.getNamespaceId(new Namespace(outPropNsKind.getVal(), abc.constants.getStringId(outPropNs.getVal(), true)), 0, true), 0, 0, new ArrayList()), true + abc.constants.getNamespaceId(new Namespace(outPropNsKind.getVal(), abc.constants.getStringId(outPropNs.getVal(), true)), outPropNsIndex.getVal(), true), 0, 0, new ArrayList()), true ); propValue = outPropValue.getVal(); break loopobjType; @@ -286,51 +356,8 @@ public class PropertyAVM2Item extends AssignableAVM2Item { } } } - } else { - List abcs = new ArrayList<>(); - abcs.add(abc); - abcs.addAll(otherABCs); - if (objType.equals("__AS3__.vec.Vector")) { - switch ("" + objSubType) { - case "int": - objType = new TypeItem("__AS3__.vec.Vector$int"); - break; - case "Number": - objType = new TypeItem("__AS3__.vec.Vector$double"); - break; - case "uint": - objType = new TypeItem("__AS3__.vec.Vector$uint"); - break; - default: - objType = new TypeItem("__AS3__.vec.Vector$object"); - } - } - loopa: - for (ABC a : abcs) { - for (InstanceInfo ii : a.instance_info) { - Multiname m = ii.getName(a.constants); - if (multinameToType(ii.name_index, a.constants).equals(objType)) { - Reference outName = new Reference<>(""); - Reference outNs = new Reference<>(""); - Reference outPropNs = new Reference<>(""); - Reference outPropNsKind = new Reference<>(1); - Reference outPropType = new Reference<>(null); - Reference outPropValue = new Reference<>(null); - if (AVM2SourceGenerator.searchPrototypeChain(false, abcs, m.getNamespace(a.constants).getName(a.constants), m.getName(a.constants, new ArrayList()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType, outPropValue)) { - objType = new TypeItem("".equals(outNs.getVal()) ? outName.getVal() : outNs.getVal() + "." + outName.getVal()); - propType = outPropType.getVal(); - propIndex = abc.constants.getMultinameId(new Multiname(Multiname.QNAME, - abc.constants.getStringId(propertyName, true), - abc.constants.getNamespaceId(new Namespace(outPropNsKind.getVal(), abc.constants.getStringId(outPropNs.getVal(), true)), 0, true), 0, 0, new ArrayList()), true - ); - propValue = outPropValue.getVal(); - - break loopa; - } - } - } - } } + } } @@ -595,21 +622,19 @@ public class PropertyAVM2Item extends AssignableAVM2Item { String cname; String pkgName = ""; cname = localData.currentClass; - if (cname != null && cname.contains(".")) { - pkgName = cname.substring(0, cname.lastIndexOf('.')); - cname = cname.substring(cname.lastIndexOf('.') + 1); - } + pkgName = localData.pkg; Reference outName = new Reference<>(""); Reference outNs = new Reference<>(""); Reference outPropNs = new Reference<>(""); Reference outPropNsKind = new Reference<>(1); + Reference outPropNsIndex = new Reference<>(0); Reference outPropType = new Reference<>(null); Reference outPropValue = new Reference<>(null); List abcs = new ArrayList<>(); abcs.add(abc); abcs.addAll(otherABCs); - if (cname != null && AVM2SourceGenerator.searchPrototypeChain(true, abcs, pkgName, cname, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType, outPropValue) && (localData.currentClass.equals("".equals(outNs.getVal()) ? outName.getVal() : outNs.getVal() + "." + outName.getVal()))) { - NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.currentClass), 0, "this", null, false, openedNamespaces); + if (cname != null && AVM2SourceGenerator.searchPrototypeChain(true, abcs, pkgName, cname, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue) && (localData.currentClass.equals("".equals(outNs.getVal()) ? outName.getVal() : outNs.getVal() + "." + outName.getVal()))) { + NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), 0, "this", null, false, openedNamespaces); nobj.setRegNumber(0); obj = nobj; } else { diff --git a/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java b/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java index f1951701a..38bf3d99f 100644 --- a/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java +++ b/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java @@ -361,6 +361,9 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { String fname = Helper.joinStrings(parts.subList(0, i + 1), "."); for (ABC a : allAbcs) { for (int c = 0; c < a.instance_info.size(); c++) { + if(a.instance_info.get(c).deleted){ + continue; + } if (a.instance_info.get(c).name_index>0 && fname.equals(a.instance_info.get(c).getName(a.constants).getNameWithNamespace(a.constants))) { if (!subtypes.isEmpty() && parts.size() > i + 1) { continue; @@ -400,6 +403,9 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { } for (ABC a : allAbcs) { for (int c = 0; c < a.instance_info.size(); c++) { + if(a.instance_info.get(c).deleted){ + continue; + } if ((a.instance_info.get(c).getName(a.constants)!=null && a == abc && a.instance_info.get(c).getName(a.constants).namespace_index == ni) || (ons.kind != Namespace.KIND_PRIVATE && a.instance_info.get(c).getName(a.constants)!=null &&a.instance_info.get(c).getName(a.constants).getNamespace(a.constants)!=null && a.instance_info.get(c).getName(a.constants).getNamespace(a.constants).hasName(ons.getName(abc.constants), a.constants))) { diff --git a/src/com/jpexs/decompiler/flash/abc/types/ClassInfo.java b/src/com/jpexs/decompiler/flash/abc/types/ClassInfo.java index baad6b391..5d807bfd9 100644 --- a/src/com/jpexs/decompiler/flash/abc/types/ClassInfo.java +++ b/src/com/jpexs/decompiler/flash/abc/types/ClassInfo.java @@ -25,7 +25,7 @@ public class ClassInfo { public int cinit_index; //MethodInfo - static initializer public Traits static_traits = new Traits(); - ; + public boolean deleted; @Override public String toString() { diff --git a/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java b/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java index d4408d74d..ab9aad7a3 100644 --- a/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java +++ b/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java @@ -36,6 +36,8 @@ public class InstanceInfo { public static final int CLASS_FINAL = 2; public static final int CLASS_INTERFACE = 4; public static final int CLASS_PROTECTEDNS = 8; + + public boolean deleted; @Override public String toString() { diff --git a/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 3b5c2add6..db7459cdc 100644 --- a/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -45,6 +45,7 @@ import java.util.logging.Logger; public class MethodBody implements Cloneable, Serializable { + public boolean deleted; boolean debugMode = false; public int method_info; public int max_stack; diff --git a/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java b/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java index 0289e57d2..08f82b6c0 100644 --- a/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java +++ b/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java @@ -18,6 +18,8 @@ package com.jpexs.decompiler.flash.abc.types; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.helpers.Helper; @@ -26,6 +28,19 @@ import java.util.List; public class MethodInfo { + + private boolean deleted; + + public void delete(ABC abc,boolean d){ + this.deleted = true; + if(body!=null){ + for(AVM2Instruction ins:body.code.code){ + if(ins.definition instanceof NewFunctionIns){ + abc.method_info.get(ins.operands[0]).delete(abc,d); + } + } + } + } public int[] param_types; public int ret_type; public int name_index; //0=no name diff --git a/src/com/jpexs/decompiler/flash/abc/types/Multiname.java b/src/com/jpexs/decompiler/flash/abc/types/Multiname.java index f8ea7b1c9..d7a21e589 100644 --- a/src/com/jpexs/decompiler/flash/abc/types/Multiname.java +++ b/src/com/jpexs/decompiler/flash/abc/types/Multiname.java @@ -41,6 +41,7 @@ public class Multiname { public int namespace_set_index = -1; public int qname_index = -1; //for TypeName public List params; //for TypeName + public boolean deleted; public boolean validType() { boolean cnt = false; diff --git a/src/com/jpexs/decompiler/flash/abc/types/Namespace.java b/src/com/jpexs/decompiler/flash/abc/types/Namespace.java index 8333e6c21..2bef4b1b7 100644 --- a/src/com/jpexs/decompiler/flash/abc/types/Namespace.java +++ b/src/com/jpexs/decompiler/flash/abc/types/Namespace.java @@ -33,6 +33,7 @@ public class Namespace { public static final String[] namePrefixes = new String[]{"", "private", "public", "", "protected", "explicit", "protected"}; public int kind; public int name_index; + public boolean deleted; public static String kindToStr(int kind) { for (int i = 0; i < nameSpaceKinds.length; i++) { diff --git a/src/com/jpexs/decompiler/flash/abc/types/NamespaceSet.java b/src/com/jpexs/decompiler/flash/abc/types/NamespaceSet.java index 3c2443993..506ef93d4 100644 --- a/src/com/jpexs/decompiler/flash/abc/types/NamespaceSet.java +++ b/src/com/jpexs/decompiler/flash/abc/types/NamespaceSet.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.abc.avm2.ConstantPool; public class NamespaceSet { + public boolean deleted; public int[] namespaces; public NamespaceSet() { diff --git a/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java b/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java index 338ed0796..d7a1bede2 100644 --- a/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java +++ b/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java @@ -27,6 +27,7 @@ import java.util.List; public class ScriptInfo { + public boolean deleted; public int init_index; //MethodInfo public Traits traits = new Traits(); @@ -77,4 +78,10 @@ public class ScriptInfo { public String toString(ABC abc, List fullyQualifiedNames) { return "method_index=" + init_index + "\r\n" + traits.toString(abc, fullyQualifiedNames); } + + public void delete(ABC abc,boolean d){ + deleted = d; + abc.method_info.get(init_index).delete(abc,d); + traits.delete(abc,d); + } } diff --git a/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java b/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java index a7472bca9..b6422efbb 100644 --- a/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java +++ b/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java @@ -47,6 +47,8 @@ public abstract class Trait implements Serializable { public static final int TRAIT_FUNCTION = 5; public static final int TRAIT_CONST = 6; + public abstract void delete(ABC abc,boolean d); + public String getModifiers(List abcTags, ABC abc, boolean isStatic) { String ret = ""; if ((kindFlags & ATTR_Override) > 0) { diff --git a/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index 8444d4d1d..aa184c8cd 100644 --- a/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -49,6 +49,25 @@ public class TraitClass extends Trait implements TraitWithSlot { private boolean classInitializerIsEmpty; + @Override + public void delete(ABC abc, boolean d) { + abc.class_info.get(class_info).deleted = d; + abc.instance_info.get(class_info).deleted = d; + + + abc.class_info.get(class_info).static_traits.delete(abc,d); + abc.method_info.get(abc.class_info.get(class_info).cinit_index).delete(abc, d); + + abc.instance_info.get(class_info).instance_traits.delete(abc,d); + abc.method_info.get(abc.instance_info.get(class_info).iinit_index).delete(abc, d); + + abc.constants.constant_namespace.get(abc.instance_info.get(class_info).protectedNS).deleted = d; + + abc.constants.constant_multiname.get(name_index).deleted = d; + } + + + @Override public int getSlotIndex() { return slot_id; diff --git a/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java b/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java index 089bc1fa1..3fdbc40a4 100644 --- a/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java +++ b/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java @@ -32,6 +32,15 @@ public class TraitFunction extends Trait implements TraitWithSlot { public int slot_id; public int method_info; + @Override + public void delete(ABC abc,boolean d) { + abc.constants.constant_multiname.get(name_index).deleted = d; + abc.method_info.get(method_info).delete(abc,d); + } + + + + @Override public int getSlotIndex() { return slot_id; diff --git a/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java b/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java index dc925b05a..22f4f1f01 100644 --- a/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java +++ b/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java @@ -32,6 +32,13 @@ public class TraitMethodGetterSetter extends Trait { public int disp_id; //compiler assigned value that helps overriding public int method_info; + + @Override + public void delete(ABC abc,boolean d) { + abc.constants.constant_multiname.get(name_index).deleted = true; + abc.method_info.get(method_info).delete(abc,d); + } + @Override public String toString(ABC abc, List fullyQualifiedNames) { return "0x" + Helper.formatAddress(fileOffset) + " " + Helper.byteArrToString(bytes) + " MethodGetterSetter " + abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " disp_id=" + disp_id + " method_info=" + method_info + " metadata=" + Helper.intArrToString(metadata); diff --git a/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java b/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java index 1ea410656..11203db3d 100644 --- a/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java +++ b/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java @@ -38,6 +38,11 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { public int value_index; public int value_kind; public GraphTargetItem assignedValue; + + @Override + public void delete(ABC abc,boolean d) { + abc.constants.constant_multiname.get(name_index).deleted = d; + } @Override public int getSlotIndex() { diff --git a/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java b/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java index 5864f5824..086938f83 100644 --- a/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java +++ b/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java @@ -37,6 +37,13 @@ public class Traits implements Serializable { public List traits = new ArrayList<>(); + + public void delete(ABC abc,boolean d){ + for(Trait t:traits){ + t.delete(abc,d); + } + } + public int addTrait(Trait t) { traits.add(t); return traits.size() - 1; diff --git a/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptParser.java b/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptParser.java index 1b1772f3f..1f80954c8 100644 --- a/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptParser.java +++ b/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptParser.java @@ -154,6 +154,12 @@ import java.util.List; */ public class ActionScriptParser { + private int swfVersion; + + public ActionScriptParser(int swfVersion){ + this.swfVersion = swfVersion; + } + private long uniqLast = 0; private final boolean debugMode = false; @@ -1517,7 +1523,8 @@ public class ActionScriptParser { boolean existsRemainder = false; boolean assocRight = false; switch (s.type) { - case NEGATE: + case NEGATE: + versionRequired(s,5); ret = expression(registerVars, inFunction, inMethod, false, variables); ret = new BitXorActionItem(null, ret, new DirectValueActionItem(4.294967295E9)); existsRemainder = true; @@ -1757,8 +1764,8 @@ public class ActionScriptParser { return retTree; } - public List actionsFromTree(int swfVersion, List tree, List constantPool) throws CompilationException { - ActionSourceGenerator gen = new ActionSourceGenerator(swfVersion, constantPool); + public List actionsFromTree(List tree, List constantPool) throws CompilationException { + ActionSourceGenerator gen = new ActionSourceGenerator(swfVersion,constantPool); List ret = new ArrayList<>(); SourceGeneratorLocalData localData = new SourceGeneratorLocalData( new HashMap(), 0, Boolean.FALSE, 0); @@ -1772,9 +1779,30 @@ public class ActionScriptParser { return ret; } - public List actionsFromString(int swfVersion,String s) throws ParseException, IOException, CompilationException { + public List actionsFromString(String s) throws ParseException, IOException, CompilationException { List constantPool = new ArrayList<>(); List tree = treeFromString(s, constantPool); - return actionsFromTree(swfVersion,tree, constantPool); + return actionsFromTree(tree, constantPool); + } + + + private void versionRequired(ParsedSymbol s, int min) throws ParseException{ + versionRequired(s.value.toString(), min, Integer.MAX_VALUE); + } + + private void versionRequired(ParsedSymbol s, int min,int max) throws ParseException{ + versionRequired(s.value.toString(), min, max); + } + + private void versionRequired(String type, int min,int max) throws ParseException{ + if(min == max && swfVersion!=min){ + throw new ParseException(type+" requires SWF version "+min, lexer.yyline()); + } + if(swfVersionmax){ + throw new ParseException(type+" requires SWF version lower than "+max, lexer.yyline()); + } } } diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index b1fb4300a..84ef7cb77 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -684,6 +684,7 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Se boolean isDocumentClass = documentClass.equals(pack.getPath().toString()); try { + abc.script_info.get(oldIndex).delete(abc, true); ActionScriptParser.compile(decompiledTextArea.getText(), abc,new ArrayList(), isDocumentClass, scriptName); //Move newly added script to its position abc.script_info.set(oldIndex, abc.script_info.get(newIndex)); @@ -701,10 +702,12 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Se View.showMessageDialog(this, AppStrings.translate("message.action.saved")); //reload(); } catch (ParseException ex) { + abc.script_info.get(oldIndex).delete(abc, false); ex.printStackTrace(); View.showMessageDialog(this, AppStrings.translate("error.action.save").replace("%error%", ex.text).replace("%line%", "" + ex.line), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); decompiledTextArea.gotoLine((int) ex.line); } catch (CompilationException ex) { + abc.script_info.get(oldIndex).delete(abc, false); ex.printStackTrace(); View.showMessageDialog(this, AppStrings.translate("error.action.save").replace("%error%", ex.text).replace("%line%", "" + ex.line), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); decompiledTextArea.gotoLine((int) ex.line); diff --git a/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java b/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java index 2ce11e887..d02475509 100644 --- a/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java @@ -748,8 +748,8 @@ public class ActionPanel extends JPanel implements ActionListener, SearchListene break; case ACTION_SAVE_DECOMPILED: try { - ActionScriptParser par = new ActionScriptParser(); - src.setActions(par.actionsFromString(mainPanel.getCurrentSwf().version,decompiledEditor.getText())); + ActionScriptParser par = new ActionScriptParser(mainPanel.getCurrentSwf().version); + src.setActions(par.actionsFromString(decompiledEditor.getText())); src.setModified(); setSource(src, false);