diff --git a/.gitignore b/.gitignore index a5fe3d50f..95ea29573 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ *.rej *.conflict~ *.identcache +*.recompiled.swf Thumbs.db /build/ /reports/ diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java index 6b490863b..260d379d8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java @@ -71,6 +71,8 @@ public class SourceGeneratorLocalData implements Serializable { public int privateNs = 0; public int protectedNs = 0; + public boolean isStatic = false; + public String getFullClass() { return pkg.add(currentClass).toRawString(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ClassPath.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ClassPath.java index a7c0beb4d..fd6b1c2e3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ClassPath.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ClassPath.java @@ -31,14 +31,13 @@ public class ClassPath { public final String className; public ClassPath(DottedChain packageStr, String className) { - this.packageStr = packageStr == null ? DottedChain.EMPTY : packageStr; + this.packageStr = packageStr == null ? DottedChain.TOPLEVEL : packageStr; this.className = className; } @Override public String toString() { - return packageStr.isEmpty() || packageStr.isTopLevel() ? IdentifiersDeobfuscation.printIdentifier(true, className) - : packageStr.toPrintableString(true) + "." + IdentifiersDeobfuscation.printIdentifier(true, className); + return packageStr.add(className).toPrintableString(true); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java index 620d314eb..69f9c2311 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java @@ -105,7 +105,7 @@ public class ScriptPack extends AS3ClassTreeItem { } public DottedChain getPathPackage() { - DottedChain packageName = DottedChain.EMPTY; + DottedChain packageName = DottedChain.TOPLEVEL; for (int t : traitIndices) { Multiname name = abc.script_info.get(scriptIndex).traits.traits.get(t).getName(abc); Namespace ns = name.getNamespace(abc.constants); 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 895111ec1..f217d9d2b 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 @@ -690,7 +690,7 @@ public class AVM2SourceGenerator implements SourceGenerator { scope = localData.scopeStack.size(); localData.scopeStack.add(new PropertyAVM2Item(null, item.functionName, abcIndex, new ArrayList<>(), localData.callStack)); } - ret.add(ins(AVM2Instructions.NewFunction, method(abcIndex.getSelectedAbc().constants.getStringId(item.functionName, true), true, false, localData.callStack, localData.pkg, item.needsActivation, item.subvariables, 0 /*Set later*/, item.hasRest, item.line, localData.currentClass, null, false, localData, item.paramTypes, item.paramNames, item.paramValues, item.body, item.retType))); + ret.add(ins(AVM2Instructions.NewFunction, method(false, abcIndex.getSelectedAbc().constants.getStringId(item.functionName, true), true, false, localData.callStack, localData.pkg, item.needsActivation, item.subvariables, 0 /*Set later*/, item.hasRest, item.line, localData.currentClass, null, false, localData, item.paramTypes, item.paramNames, item.paramValues, item.body, item.retType))); if (!item.functionName.isEmpty()) { ret.add(ins(AVM2Instructions.Dup)); ret.add(ins(AVM2Instructions.GetScopeObject, scope)); @@ -1175,14 +1175,14 @@ public class AVM2SourceGenerator implements SourceGenerator { generateTraitsPhase3(initScope, isInterface, name, superName, true, localData, traitItems, classInfo.static_traits, st, new HashMap<>(), class_index); int init = 0; if (constructor == null || isInterface) { - instanceInfo.iinit_index = init = method(0, false, isInterface, new ArrayList<>(), pkg, false, new ArrayList<>(), initScope + 1, false, 0, isInterface ? null : name, extendsVal != null ? extendsVal.toString() : null, true, localData, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), TypeItem.UNBOUNDED/*?? FIXME*/); + instanceInfo.iinit_index = init = method(false, 0, false, isInterface, new ArrayList<>(), pkg, false, new ArrayList<>(), initScope + 1, false, 0, isInterface ? null : name, extendsVal != null ? extendsVal.toString() : null, true, localData, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), TypeItem.UNBOUNDED/*?? FIXME*/); } else { MethodAVM2Item m = (MethodAVM2Item) constructor; - instanceInfo.iinit_index = init = method(0, false, false, new ArrayList<>(), pkg, m.needsActivation, m.subvariables, initScope + 1, m.hasRest, m.line, name, extendsVal != null ? extendsVal.toString() : null, true, localData, m.paramTypes, m.paramNames, m.paramValues, m.body, TypeItem.UNBOUNDED/*?? FIXME*/); + instanceInfo.iinit_index = init = method(false, 0, false, false, new ArrayList<>(), pkg, m.needsActivation, m.subvariables, initScope + 1, m.hasRest, m.line, name, extendsVal != null ? extendsVal.toString() : null, true, localData, m.paramTypes, m.paramNames, m.paramValues, m.body, TypeItem.UNBOUNDED/*?? FIXME*/); } //Class initializer - int staticMi = method(0, false, false, new ArrayList<>(), pkg, staticNeedsActivation, sinitVariables, initScope + (implementsStr.isEmpty() ? 0 : 1), false, 0, isInterface ? null : name, superName, false, localData, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), staticInit, TypeItem.UNBOUNDED); + int staticMi = method(true, 0, false, false, new ArrayList<>(), pkg, staticNeedsActivation, sinitVariables, initScope + (implementsStr.isEmpty() ? 0 : 1), false, 0, isInterface ? null : name, superName, false, localData, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), staticInit, TypeItem.UNBOUNDED); MethodBody sinitBody = abcIndex.getSelectedAbc().findBody(staticMi); List sinitcode = new ArrayList<>(); @@ -1209,6 +1209,7 @@ public class AVM2SourceGenerator implements SourceGenerator { } if (isStatic && val != null) { sinitcode.add(ins(AVM2Instructions.FindProperty, traitName(ns, tname))); + localData.isStatic = true; sinitcode.addAll(toInsList(val.toSource(localData, this))); sinitcode.add(ins(isConst ? AVM2Instructions.InitProperty : AVM2Instructions.SetProperty, traitName(ns, tname))); } @@ -1216,6 +1217,7 @@ public class AVM2SourceGenerator implements SourceGenerator { //do not init basic values, that can be stored in trait if (!(val instanceof IntegerValueAVM2Item) && !(val instanceof StringAVM2Item) && !(val instanceof BooleanAVM2Item) && !(val instanceof NullAVM2Item) && !(val instanceof UndefinedAVM2Item)) { initcode.add(ins(AVM2Instructions.GetLocal0)); + localData.isStatic = false; initcode.addAll(toInsList(val.toSource(localData, this))); initcode.add(ins(isConst ? AVM2Instructions.InitProperty : AVM2Instructions.SetProperty, traitName(ns, tname))); } @@ -1366,7 +1368,7 @@ public class AVM2SourceGenerator implements SourceGenerator { return false; } - public int method(int name_index, boolean subMethod, boolean isInterface, List callStack, DottedChain pkg, boolean needsActivation, List subvariables, int initScope, boolean hasRest, int line, String className, String superType, boolean constructor, SourceGeneratorLocalData localData, List paramTypes, List paramNames, List paramValues, List body, GraphTargetItem retType) throws CompilationException { + public int method(boolean isStatic, int name_index, boolean subMethod, boolean isInterface, List callStack, DottedChain pkg, boolean needsActivation, List subvariables, int initScope, boolean hasRest, int line, String className, String superType, boolean constructor, SourceGeneratorLocalData localData, List paramTypes, List paramNames, List paramValues, List body, GraphTargetItem retType) throws CompilationException { //Reference hasArgs = new Reference<>(Boolean.FALSE); //calcRegisters(localData,needsActivation,paramNames,subvariables,body, hasArgs); SourceGeneratorLocalData newlocalData = new SourceGeneratorLocalData(new HashMap<>(), 1, true, 0); @@ -1378,6 +1380,7 @@ public class AVM2SourceGenerator implements SourceGenerator { newlocalData.documentClass = localData.documentClass; newlocalData.privateNs = localData.privateNs; newlocalData.protectedNs = localData.protectedNs; + newlocalData.isStatic = isStatic; newlocalData.subMethod = subMethod; localData = newlocalData; @@ -1799,7 +1802,7 @@ public class AVM2SourceGenerator implements SourceGenerator { } } - if ((type instanceof TypeItem) && (((TypeItem) type).fullTypeName.equals("Namespace"))) { + if ((type instanceof TypeItem) && (((TypeItem) type).fullTypeName.equals(DottedChain.NAMESPACE))) { isNs = true; } @@ -1833,7 +1836,9 @@ public class AVM2SourceGenerator implements SourceGenerator { if (custom != null) { PropertyAVM2Item prop = new PropertyAVM2Item(null, custom, abcIndex, openedNamespaces, new ArrayList<>()); Reference value = new Reference<>(null); - prop.resolve(localData, new Reference<>(null), new Reference<>(null), new Reference<>(0), value); + Reference outAbc = new Reference<>(null); + + prop.resolve(localData, new Reference<>(null), new Reference<>(null), new Reference<>(0), value, outAbc); boolean resolved = true; if (value.getVal() == null) { resolved = false; @@ -1864,7 +1869,9 @@ public class AVM2SourceGenerator implements SourceGenerator { throw new CompilationException("Namespace not defined", line); } - namespace = value.getVal().value_index; + namespace = abcIndex.getSelectedAbc().constants.getNamespaceId(new Namespace(Namespace.KIND_NAMESPACE, + abcIndex.getSelectedAbc().constants.getStringId(outAbc.getVal().constants.getNamespace(value.getVal().value_index).getName(outAbc.getVal().constants), true) + ), 0, true); } return namespace; } @@ -1980,10 +1987,10 @@ public class AVM2SourceGenerator implements SourceGenerator { if (mai.isStatic() != generateStatic) { continue; } - ((TraitMethodGetterSetter) traits[k]).method_info = method(abcIndex.getSelectedAbc().constants.getStringId(mai.functionName, true), false, isInterface, new ArrayList<>(), mai.pkg, mai.needsActivation, mai.subvariables, methodInitScope + (mai.isStatic() ? 0 : 1), mai.hasRest, mai.line, className, superName, false, localData, mai.paramTypes, mai.paramNames, mai.paramValues, mai.body, mai.retType); + ((TraitMethodGetterSetter) traits[k]).method_info = method(mai.isStatic(), abcIndex.getSelectedAbc().constants.getStringId(mai.functionName, true), false, isInterface, new ArrayList<>(), mai.pkg, mai.needsActivation, mai.subvariables, methodInitScope + (mai.isStatic() ? 0 : 1), mai.hasRest, mai.line, className, superName, false, localData, mai.paramTypes, mai.paramNames, mai.paramValues, mai.body, mai.retType); } else if (item instanceof FunctionAVM2Item) { FunctionAVM2Item fai = (FunctionAVM2Item) item; - ((TraitFunction) traits[k]).method_info = method(abcIndex.getSelectedAbc().constants.getStringId(fai.functionName, true), false, isInterface, new ArrayList<>(), fai.pkg, fai.needsActivation, fai.subvariables, methodInitScope, fai.hasRest, fai.line, className, superName, false, localData, fai.paramTypes, fai.paramNames, fai.paramValues, fai.body, fai.retType); + ((TraitFunction) traits[k]).method_info = method(false, abcIndex.getSelectedAbc().constants.getStringId(fai.functionName, true), false, isInterface, new ArrayList<>(), fai.pkg, fai.needsActivation, fai.subvariables, methodInitScope, fai.hasRest, fai.line, className, superName, false, localData, fai.paramTypes, fai.paramNames, fai.paramValues, fai.body, fai.retType); } } } @@ -2256,20 +2263,20 @@ public class AVM2SourceGenerator implements SourceGenerator { return TypeItem.UNBOUNDED; } - public static boolean searchPrototypeChain(int privateNs, int protectedNs, boolean instanceOnly, AbcIndexing abc, DottedChain pkg, String obj, String propertyName, Reference outName, Reference outNs, Reference outPropNs, Reference outPropNsKind, Reference outPropNsIndex, Reference outPropType, Reference outPropValue) { - if (searchPrototypeChain(privateNs, instanceOnly, abc, pkg, obj, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue)) { + public static boolean searchPrototypeChain(int privateNs, int protectedNs, boolean instanceOnly, AbcIndexing abc, DottedChain pkg, String obj, String propertyName, Reference outName, Reference outNs, Reference outPropNs, Reference outPropNsKind, Reference outPropNsIndex, Reference outPropType, Reference outPropValue, Reference outPropValueAbc) { + if (searchPrototypeChain(privateNs, instanceOnly, abc, pkg, obj, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc)) { return true; } - if (searchPrototypeChain(protectedNs, instanceOnly, abc, pkg, obj, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue)) { + if (searchPrototypeChain(protectedNs, instanceOnly, abc, pkg, obj, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc)) { return true; } - if (searchPrototypeChain(0, instanceOnly, abc, pkg, obj, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue)) { + if (searchPrototypeChain(0, instanceOnly, abc, pkg, obj, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc)) { return true; } return false; } - private static boolean searchPrototypeChain(int selectedNs, boolean instanceOnly, AbcIndexing abc, DottedChain pkg, String obj, String propertyName, Reference outName, Reference outNs, Reference outPropNs, Reference outPropNsKind, Reference outPropNsIndex, Reference outPropType, Reference outPropValue) { + private static boolean searchPrototypeChain(int selectedNs, boolean instanceOnly, AbcIndexing abc, DottedChain pkg, String obj, String propertyName, Reference outName, Reference outNs, Reference outPropNs, Reference outPropNsKind, Reference outPropNsIndex, Reference outPropType, Reference outPropValue, Reference outPropValueAbc) { AbcIndexing.TraitIndex sp = abc.findScriptProperty(pkg.add(propertyName)); if (sp == null) { @@ -2287,6 +2294,7 @@ public class AVM2SourceGenerator implements SourceGenerator { outPropNsIndex.setVal(selectedNs == 0 ? 0 : sp.abc.constants.getNamespaceSubIndex(selectedNs)); outPropType.setVal(sp.returnType); outPropValue.setVal(sp.value); + outPropValueAbc.setVal(sp.abc); return true; } return false; 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 8537e2dbf..5afd4033a 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 @@ -427,7 +427,7 @@ public class AbcIndexing { propValue = new ValueKind(tsc.value_index, tsc.value_kind); } if (map != null) { - PropertyDef dp = new PropertyDef(t.getName(abc).getName(abc.constants, new ArrayList<>() /*?*/, true), multinameToType(name_index, abc.constants), abc, abc.constants.getMultiname(t.name_index).namespace_index); + PropertyDef dp = new PropertyDef(t.getName(abc).getName(abc.constants, new ArrayList<>() /*?*/, true), multinameToType(name_index, abc.constants), abc, abc.constants.constant_multiname.get(t.name_index).namespace_index); map.put(dp, new TraitIndex(t, abc, getTraitReturnType(abc, t), propValue, multinameToType(name_index, abc.constants))); } if (mapNs != null) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java index 2f40156d5..43fc76db1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java @@ -2273,7 +2273,7 @@ public class ActionScript3Parser { private PackageAVM2Item parsePackage(List openedNamespaces) throws IOException, AVM2ParseException, CompilationException { List items = new ArrayList<>(); expectedType(SymbolType.PACKAGE); - DottedChain name = DottedChain.EMPTY; + DottedChain name = DottedChain.TOPLEVEL; ParsedSymbol s = lex(); if (s.type != SymbolType.CURLY_OPEN) { expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/CallAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/CallAVM2Item.java index 99d118efe..67d69c75e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/CallAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/CallAVM2Item.java @@ -81,7 +81,9 @@ public class CallAVM2Item extends AVM2Item { Reference outPropNsIndex = new Reference<>(0); Reference outPropType = new Reference<>(null); Reference outPropValue = new Reference<>(null); - if (cname != null && AVM2SourceGenerator.searchPrototypeChain(localData.privateNs, localData.protectedNs, true, g.abcIndex, pkgName, cname, n.getVariableName(), outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue)) { + Reference outPropValueABC = new Reference<>(null); + + if (cname != null && AVM2SourceGenerator.searchPrototypeChain(localData.privateNs, localData.protectedNs, true, g.abcIndex, pkgName, cname, n.getVariableName(), outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueABC)) { NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), n.line, "this", null, false, n.openedNamespaces); nobj.setRegNumber(0); obj = nobj; @@ -115,7 +117,9 @@ public class CallAVM2Item extends AVM2Item { Reference outPropNsIndex = new Reference<>(0); Reference outPropType = new Reference<>(null); Reference outPropValue = new Reference<>(null); - if (cname != null && AVM2SourceGenerator.searchPrototypeChain(localData.privateNs, localData.protectedNs, true, g.abcIndex, pkgName, cname, prop.propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue) && (localData.currentClass.equals("".equals(outNs.getVal()) ? outName.getVal() : outNs.getVal() + "." + outName.getVal()))) { + Reference outPropValueAbc = new Reference<>(null); + + if (cname != null && AVM2SourceGenerator.searchPrototypeChain(localData.privateNs, localData.protectedNs, true, g.abcIndex, pkgName, cname, prop.propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc) && (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/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ConstructSomethingAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ConstructSomethingAVM2Item.java index 27ba50f39..861bdd13b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ConstructSomethingAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ConstructSomethingAVM2Item.java @@ -67,6 +67,12 @@ public class ConstructSomethingAVM2Item extends CallAVM2Item { if (resname instanceof TypeItem) { TypeItem prop = (TypeItem) resname; + if (localData.isStatic && localData.pkg.add(localData.currentClass).equals(prop.fullTypeName)) { + return toSourceMerge(localData, generator, + new AVM2Instruction(0, AVM2Instructions.GetLocal0, new int[]{}), arguments, + new AVM2Instruction(0, AVM2Instructions.Construct, new int[]{arguments.size()})); + + } int type_index = AVM2SourceGenerator.resolveType(localData, resname, ((AVM2SourceGenerator) generator).abcIndex); return toSourceMerge(localData, generator, new AVM2Instruction(0, AVM2Instructions.FindPropertyStrict, new int[]{type_index, arguments.size()}), arguments, 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 d47afb701..60b97a6ea 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 @@ -109,11 +109,12 @@ public class PropertyAVM2Item extends AssignableAVM2Item { } } - public void resolve(SourceGeneratorLocalData localData, Reference objectType, Reference propertyType, Reference propertyIndex, Reference propertyValue) { + public void resolve(SourceGeneratorLocalData localData, Reference objectType, Reference propertyType, Reference propertyIndex, Reference propertyValue, Reference propertyValueABC) { GraphTargetItem thisType = new TypeItem(localData.getFullClass()); GraphTargetItem objType = null; GraphTargetItem objSubType = null; ValueKind propValue = null; + ABC propValueAbc = null; if (object != null) { GraphTargetItem oretType = object.returnType(); if (oretType instanceof UnresolvedAVM2Item) { @@ -216,7 +217,8 @@ public class PropertyAVM2Item extends AssignableAVM2Item { Reference outPropNsIndex = new Reference<>(0); Reference outPropType = new Reference<>(null); Reference outPropValue = new Reference<>(null); - if (AVM2SourceGenerator.searchPrototypeChain(localData.privateNs, localData.protectedNs, false, abc, ftn.getWithoutLast(), ftn.getLast(), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue)) { + Reference outPropValueAbc = new Reference<>(null); + if (AVM2SourceGenerator.searchPrototypeChain(localData.privateNs, localData.protectedNs, false, abc, ftn.getWithoutLast(), ftn.getLast(), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc)) { objType = new TypeItem(outNs.getVal().add(outName.getVal())); propType = outPropType.getVal(); propIndex = abc.getSelectedAbc().constants.getMultinameId(new Multiname(Multiname.QNAME, @@ -224,6 +226,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { abc.getSelectedAbc().constants.getNamespaceId(new Namespace(outPropNsKind.getVal(), outPropNs.getVal() == null || outPropNs.getVal().isEmpty() ? 0 : abc.getSelectedAbc().constants.getStringId(outPropNs.getVal(), true)), outPropNsIndex.getVal(), true), 0, 0, new ArrayList<>()), true ); propValue = outPropValue.getVal(); + propValueAbc = outPropValueAbc.getVal(); } } @@ -273,6 +276,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { if (t instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst) t; propValue = new ValueKind(tsc.value_index, tsc.value_kind); + propValueAbc = abc.getSelectedAbc(); } break loopobjType; } @@ -285,6 +289,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { if (t instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst) t; propValue = new ValueKind(tsc.value_index, tsc.value_kind); + propValueAbc = abc.getSelectedAbc(); } break loopobjType; } @@ -303,6 +308,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { if (t instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst) t; propValue = new ValueKind(tsc.value_index, tsc.value_kind); + propValueAbc = abc.getSelectedAbc(); } break loopobjType; } @@ -319,8 +325,9 @@ public class PropertyAVM2Item extends AssignableAVM2Item { Reference outPropNsIndex = new Reference<>(0); Reference outPropType = new Reference<>(null); Reference outPropValue = new Reference<>(null); + Reference outPropValueAbc = new Reference<>(null); if (p != null && (p.objType instanceof TypeItem)) { - if (AVM2SourceGenerator.searchPrototypeChain(localData.privateNs, localData.protectedNs, false, abc, nsname, (((TypeItem) p.objType).fullTypeName.getLast()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue)) { + if (AVM2SourceGenerator.searchPrototypeChain(localData.privateNs, localData.protectedNs, false, abc, nsname, (((TypeItem) p.objType).fullTypeName.getLast()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc)) { objType = new TypeItem("".equals(outNs.getVal()) ? outName.getVal() : outNs.getVal() + "." + outName.getVal()); propType = p.returnType; propIndex = abc.getSelectedAbc().constants.getMultinameId(new Multiname(Multiname.QNAME, @@ -328,6 +335,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { abc.getSelectedAbc().constants.getNamespaceId(new Namespace(outPropNsKind.getVal(), outPropNs.getVal() == null || outPropNs.getVal().isEmpty() ? 0 : abc.getSelectedAbc().constants.getStringId(outPropNs.getVal(), true)), outPropNsIndex.getVal(), true), 0, 0, new ArrayList<>()), true ); propValue = p.value; + propValueAbc = outPropValueAbc.getVal(); break loopobjType; } } @@ -356,9 +364,11 @@ public class PropertyAVM2Item extends AssignableAVM2Item { propType = TypeItem.UNBOUNDED; objType = TypeItem.UNBOUNDED; propValue = null; + propValueAbc = null; } propertyValue.setVal(propValue); + propertyValueABC.setVal(propValueAbc); propertyIndex.setVal(propIndex); propertyType.setVal(propType); objectType.setVal(objType); @@ -369,7 +379,8 @@ public class PropertyAVM2Item extends AssignableAVM2Item { Reference propType = new Reference<>(null); Reference propIndex = new Reference<>(0); Reference outPropValue = new Reference<>(null); - resolve(localData, objType, propType, propIndex, outPropValue); + Reference outPropValueAbc = new Reference<>(null); + resolve(localData, objType, propType, propIndex, outPropValue, outPropValueAbc); return propIndex.getVal(); } @@ -538,7 +549,9 @@ public class PropertyAVM2Item extends AssignableAVM2Item { Reference propType = new Reference<>(null); Reference propIndex = new Reference<>(0); Reference outPropValue = new Reference<>(null); - resolve(new SourceGeneratorLocalData(new HashMap<>(), 0, false, 0)/*???*/, objType, propType, propIndex, outPropValue); + Reference outPropValueAbc = new Reference<>(null); + + resolve(new SourceGeneratorLocalData(new HashMap<>(), 0, false, 0)/*???*/, objType, propType, propIndex, outPropValue, outPropValueAbc); return propType.getVal(); } @@ -549,7 +562,9 @@ public class PropertyAVM2Item extends AssignableAVM2Item { Reference propType = new Reference<>(null); Reference propIndex = new Reference<>(0); Reference outPropValue = new Reference<>(null); - resolve(localData, objType, propType, propIndex, outPropValue); + Reference outPropValueAbc = new Reference<>(null); + + resolve(localData, objType, propType, propIndex, outPropValue, outPropValueAbc); int propertyId = propIndex.getVal(); Object obj = resolveObject(localData, generator); @@ -611,10 +626,12 @@ public class PropertyAVM2Item extends AssignableAVM2Item { Reference outPropNsIndex = new Reference<>(0); Reference outPropType = new Reference<>(null); Reference outPropValue = new Reference<>(null); + Reference outPropValueAbc = new Reference<>(null); + /*List abcs = new ArrayList<>(); abcs.add(abc); abcs.addAll(otherABCs);*/ - if (!localData.subMethod && cname != null && AVM2SourceGenerator.searchPrototypeChain(localData.privateNs, localData.protectedNs, true, abc, pkgName, cname, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue) && (localData.currentClass.equals(DottedChain.EMPTY.equals(outNs.getVal()) ? outName.getVal() : outNs.getVal().add(outName.getVal())))) { + if (!localData.subMethod && cname != null && AVM2SourceGenerator.searchPrototypeChain(localData.privateNs, localData.protectedNs, true, abc, pkgName, cname, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc) && (localData.currentClass.equals(outNs.getVal().add(outName.getVal())))) { NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), 0, "this", null, false, openedNamespaces); nobj.setRegNumber(0); obj = nobj; @@ -623,7 +640,9 @@ public class PropertyAVM2Item extends AssignableAVM2Item { Reference propType = new Reference<>(null); Reference propIndex = new Reference<>(0); Reference propValue = new Reference<>(null); - resolve(localData, objType, propType, propIndex, outPropValue); + Reference propValueAbc = new Reference<>(null); + + resolve(localData, objType, propType, propIndex, outPropValue, propValueAbc); obj = ins(AVM2Instructions.FindPropertyStrict, propIndex.getVal()); } } @@ -637,7 +656,9 @@ public class PropertyAVM2Item extends AssignableAVM2Item { Reference propType = new Reference<>(null); Reference propIndex = new Reference<>(0); Reference outPropValue = new Reference<>(null); - resolve(localData, objType, propType, propIndex, outPropValue); + Reference outPropValueAbc = new Reference<>(null); + + resolve(localData, objType, propType, propIndex, outPropValue, outPropValueAbc); int propertyId = propIndex.getVal(); Object obj = resolveObject(localData, generator); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java index 231a1b3e9..3d85e45c8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java @@ -32,7 +32,7 @@ public class DottedChain implements Serializable { public static final DottedChain EMPTY = new DottedChain(true); - public static final DottedChain TOPLEVEL = new DottedChain(""); + public static final DottedChain TOPLEVEL = new DottedChain(); public static final DottedChain BOOLEAN = new DottedChain("Boolean"); @@ -70,8 +70,10 @@ public class DottedChain implements Serializable { private boolean isNull = false; public static final DottedChain parse(String name) { - if (name == null || name.isEmpty()) { + if (name == null) { return DottedChain.EMPTY; + } else if (name.isEmpty()) { + return DottedChain.TOPLEVEL; } else { return new DottedChain(name.split("\\.")); } @@ -86,6 +88,7 @@ public class DottedChain implements Serializable { public DottedChain(DottedChain src) { this(src.parts); + this.isNull = src.isNull; } public DottedChain(List parts) { @@ -95,8 +98,13 @@ public class DottedChain implements Serializable { } public DottedChain(String... parts) { - length = parts.length; - this.parts = parts; + if (parts.length == 1 && parts[0].isEmpty()) { + length = 0; + this.parts = new String[0]; + } else { + length = parts.length; + this.parts = parts; + } hash = calcHash(); } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/DirectEditingTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/DirectEditingTest.java index 89fb2fd2b..7b1101311 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/DirectEditingTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/DirectEditingTest.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException; import com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScript3Parser; import com.jpexs.decompiler.flash.abc.types.ConvertData; +import com.jpexs.decompiler.flash.abc.types.ScriptInfo; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.parser.ActionParseException; import com.jpexs.decompiler.flash.action.parser.script.ActionScript2Parser; @@ -29,12 +30,14 @@ import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.CodeFormatting; import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.TranslateException; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -88,10 +91,14 @@ public class DirectEditingTest extends FileTestBase { System.out.println("Recompiling:" + classPathString + "..."); en.toSource(htw, abc.script_info.get(s).traits.traits, new ConvertData(), ScriptExportMode.AS, false); String original = htw.toString(); - ActionScript3Parser.compile(original, abc, allAbcs, false, en.getClassPath().className + ".as", abc.instance_info.size()); + List otherAbcs = new ArrayList<>(allAbcs); + otherAbcs.remove(abc); + ActionScript3Parser.compile(original, abc, otherAbcs, false, en.getClassPath().className + ".as", abc.instance_info.size()); //remove last compiled script: - abc.script_info.remove(abc.script_info.size() - 1); + ScriptInfo n = abc.script_info.remove(abc.script_info.size() - 1); + abc.script_info.set(s, n); + ((Tag) abc.parentTag).setModified(true); } } } else { @@ -125,10 +132,18 @@ public class DirectEditingTest extends FileTestBase { if (!as3.equals(as2)) { fail("ActionScript is different: " + asm.getSwf().getShortFileName() + "/" + asm.toString()); } + asm.setModified(); } catch (InterruptedException | IOException | OutOfMemoryError | TranslateException | StackOverflowError ex) { } } } + String nFilePath = filePath.substring(0, filePath.length() - 4); //remove .swf + nFilePath += ".recompiled.swf"; + + try (FileOutputStream fos = new FileOutputStream(nFilePath)) { + swf.saveTo(fos); + } + //TODO: try tu run it in debug flashplayer (?) } catch (Exception ex) { fail("Exception during decompilation: " + filePath, ex); }