diff --git a/trunk/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java b/trunk/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java index 6dcc49d68..3498bcfe4 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java +++ b/trunk/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash; import com.jpexs.decompiler.flash.abc.types.ABCException; import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.graph.GraphTargetItem; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; @@ -45,6 +46,7 @@ public class SourceGeneratorLocalData implements Serializable { public List callStack = new ArrayList<>(); public Map> traitUsages = new HashMap<>(); public String pkg = ""; + public List scopeStack = new ArrayList(); public SourceGeneratorLocalData(HashMap registerVars, Integer inFunction, Boolean inMethod, Integer forInLevel) { this.registerVars = registerVars; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/WithAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/WithAVM2Item.java index 295538362..08f23640e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/WithAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/WithAVM2Item.java @@ -16,9 +16,15 @@ */ package com.jpexs.decompiler.flash.abc.avm2.model; +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.AVM2SourceGenerator; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.AssignableAVM2Item; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.decompiler.graph.model.LocalData; import java.util.ArrayList; @@ -28,6 +34,7 @@ public class WithAVM2Item extends AVM2Item { public GraphTargetItem scope; public List items; + public List subvariables = new ArrayList(); public WithAVM2Item(AVM2Instruction instruction, GraphTargetItem scope, List items) { super(instruction, NOPRECEDENCE); @@ -73,4 +80,10 @@ public class WithAVM2Item extends AVM2Item { public boolean hasReturnValue() { return false; } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + return ((AVM2SourceGenerator) generator).generate(localData, this); + } + } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/WithObjectAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/WithObjectAVM2Item.java index cc5148f65..738d1f788 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/WithObjectAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/WithObjectAVM2Item.java @@ -16,11 +16,16 @@ */ package com.jpexs.decompiler.flash.abc.avm2.model; +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.decompiler.graph.model.LocalData; +import java.util.List; public class WithObjectAVM2Item extends AVM2Item { @@ -45,4 +50,10 @@ public class WithObjectAVM2Item extends AVM2Item { public boolean hasReturnValue() { return false; } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + return scope.toSource(localData, generator); + } + } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/TryAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/TryAVM2Item.java index 993785d34..64e8fbb32 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/TryAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/TryAVM2Item.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc.avm2.model.clauses; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.abc.avm2.parser.script.AVM2SourceGenerator; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.AssignableAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.parser.script.NameAVM2Item; import com.jpexs.decompiler.flash.abc.types.ABCException; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; @@ -40,6 +41,7 @@ public class TryAVM2Item extends AVM2Item implements Block { public List catchExceptions2; public List> catchCommands; public List finallyCommands; + public List> catchVariables = new ArrayList>(); @Override public List> getSubs() { diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java index 0b6e985af..8ee0f8f86 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java @@ -52,18 +52,22 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopScopeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushWithIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceAIns; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.BooleanAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FloatValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ReturnValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ReturnVoidAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ThrowAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.WithAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.WithObjectAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForEachInAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForInAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.TryAVM2Item; @@ -432,6 +436,21 @@ public class AVM2SourceGenerator implements SourceGenerator { return ret; } + public List generate(SourceGeneratorLocalData localData, WithAVM2Item item) throws CompilationException { + + List ret = new ArrayList<>(); + ret.addAll(item.scope.toSource(localData, this)); + Reference tempReg = new Reference<>(0); + ret.addAll(AssignableAVM2Item.dupSetTemp(localData, this, tempReg)); + localData.scopeStack.add(new WithObjectAVM2Item(null, new LocalRegAVM2Item(null, tempReg.getVal(), null))); + ret.add(ins(new PushWithIns())); + ret.addAll(generate(localData, item.items)); + ret.add(ins(new PopScopeIns())); + ret.addAll(AssignableAVM2Item.killTemp(localData, this, Arrays.asList(tempReg))); + localData.scopeStack.remove(localData.scopeStack.size() - 1); + return ret; + } + @Override public List generate(SourceGeneratorLocalData localData, ForItem item) throws CompilationException { List ret = new ArrayList<>(); @@ -585,7 +604,6 @@ public class AVM2SourceGenerator implements SourceGenerator { List ret = new ArrayList<>(); boolean newFinallyReg = false; - int firstId = 0; List newex = new ArrayList<>(); int aloneFinallyEx = -1; int finallyEx = -1; @@ -621,20 +639,80 @@ public class AVM2SourceGenerator implements SourceGenerator { localData.finallyCatches.add(finId); } List tryCmds = generateToInsList(localData, item.tryCommands); + + //int i = firstId + item.catchCommands.size() - 1; + List catches = new ArrayList<>(); + Reference tempReg = new Reference<>(0); + + List currentExceptionIds = new ArrayList<>(); List> catchCmds = new ArrayList<>(); for (int c = 0; c < item.catchCommands.size(); c++) { - catchCmds.add(generateToInsList(localData, item.catchCommands.get(c))); + int i = localData.exceptions.size(); + localData.exceptions.add(newex.get(c)); + + currentExceptionIds.add(i); + + //Reference tempReg=new Reference<>(0); + List catchCmd = new ArrayList<>(); + catchCmd.add(ins(new NewCatchIns(), i)); + catchCmd.addAll(toInsList(AssignableAVM2Item.dupSetTemp(localData, this, tempReg))); + catchCmd.add(ins(new DupIns())); + catchCmd.add(ins(new PushScopeIns())); + catchCmd.add(ins(new SwapIns())); + catchCmd.add(ins(new SetSlotIns(), 1)); + + for (AssignableAVM2Item a : item.catchVariables.get(c)) { + GraphTargetItem r = a; + if (r instanceof UnresolvedAVM2Item) { + r = ((UnresolvedAVM2Item) r).resolved; + } + if (r instanceof NameAVM2Item) { + NameAVM2Item n = (NameAVM2Item) r; + if (item.catchExceptions2.get(c).getVariableName().equals(n.getVariableName())) { + n.setSlotScope(localData.scopeStack.size()); + } + } + } + localData.scopeStack.add(new LocalRegAVM2Item(null, tempReg.getVal(), null)); + catchCmd.addAll(generateToInsList(localData, item.catchCommands.get(c))); + localData.scopeStack.remove(localData.scopeStack.size() - 1); + catchCmd.add(ins(new PopScopeIns())); + catchCmd.addAll(toInsList(AssignableAVM2Item.killTemp(localData, this, Arrays.asList(tempReg)))); + catchCmds.add(catchCmd); + } + for (int c = item.catchCommands.size() - 1; c >= 0; c--) { + List preCatches = new ArrayList<>(); + /*preCatches.add(ins(new GetLocal0Ins())); + preCatches.add(ins(new PushScopeIns())); + preCatches.add(AssignableAVM2Item.generateGetLoc(localData.activationReg)); + preCatches.add(ins(new PushScopeIns()));*/ + for (GraphTargetItem s : localData.scopeStack) { + preCatches.addAll(toInsList(s.toSource(localData, this))); + if (s instanceof WithObjectAVM2Item) { + preCatches.add(ins(new PushWithIns())); + } else { + preCatches.add(ins(new PushScopeIns())); + } + } + + //catchCmds.add(catchCmd); + preCatches.addAll(catchCmds.get(c)); + catches.addAll(0, preCatches); + catches.add(0, new ExceptionMarkAVM2Instruction(currentExceptionIds.get(c), MARK_E_TARGET)); + catches.add(0, ins(new JumpIns(), insToBytes(catches).length)); } - firstId = localData.exceptions.size(); if (aloneFinallyEx > -1) { - aloneFinallyEx += firstId; + localData.exceptions.add(newex.get(aloneFinallyEx)); + aloneFinallyEx = localData.exceptions.size() - 1; + } if (finallyEx > -1) { - finallyEx += firstId; + localData.exceptions.add(newex.get(finallyEx)); + finallyEx = localData.exceptions.size() - 1; } - for (int i = firstId; i < firstId + item.catchExceptions2.size(); i++) { + for (int i : currentExceptionIds) { ret.add(new ExceptionMarkAVM2Instruction(i, MARK_E_START)); } if (aloneFinallyEx > -1) { @@ -646,43 +724,23 @@ public class AVM2SourceGenerator implements SourceGenerator { ret.addAll(tryCmds); - for (int i = firstId; i < firstId + item.catchExceptions2.size(); i++) { + for (int i : currentExceptionIds) { ret.add(new ExceptionMarkAVM2Instruction(i, MARK_E_END)); } if (aloneFinallyEx > -1) { ret.add(new ExceptionMarkAVM2Instruction(aloneFinallyEx, MARK_E_END)); } - int i = firstId + item.catchCommands.size() - 1; - List catches = new ArrayList<>(); - Reference tempReg = new Reference<>(0); - for (int c = item.catchCommands.size() - 1; c >= 0; c--) { - List preCatches = new ArrayList<>(); - preCatches.add(ins(new GetLocal0Ins())); - preCatches.add(ins(new PushScopeIns())); - preCatches.add(AssignableAVM2Item.generateGetLoc(localData.activationReg)); - preCatches.add(ins(new PushScopeIns())); - preCatches.add(ins(new NewCatchIns(), i)); - preCatches.addAll(toInsList(AssignableAVM2Item.dupSetTemp(localData, this, tempReg))); - preCatches.add(ins(new DupIns())); - preCatches.add(ins(new PushScopeIns())); - preCatches.add(ins(new SwapIns())); - preCatches.add(ins(new SetSlotIns(), 1)); - preCatches.addAll(catchCmds.get(c)); - preCatches.add(ins(new PopScopeIns())); - preCatches.addAll(toInsList(AssignableAVM2Item.killTemp(localData, this, Arrays.asList(tempReg)))); - catches.addAll(0, preCatches); - catches.add(0, new ExceptionMarkAVM2Instruction(i, MARK_E_TARGET)); - i--; - catches.add(0, ins(new JumpIns(), insToBytes(catches).length)); - } - if (aloneFinallyEx > -1) { List preCatches = new ArrayList<>(); - preCatches.add(ins(new GetLocal0Ins())); - preCatches.add(ins(new PushScopeIns())); - preCatches.add(AssignableAVM2Item.generateGetLoc(localData.activationReg)); - preCatches.add(ins(new PushScopeIns())); + for (GraphTargetItem s : localData.scopeStack) { + preCatches.addAll(toInsList(s.toSource(localData, this))); + if (s instanceof WithObjectAVM2Item) { + preCatches.add(ins(new PushWithIns())); + } else { + preCatches.add(ins(new PushScopeIns())); + } + } preCatches.add(ins(new NewCatchIns(), aloneFinallyEx)); preCatches.addAll(toInsList(AssignableAVM2Item.dupSetTemp(localData, this, tempReg))); preCatches.add(ins(new PushScopeIns())); @@ -700,10 +758,14 @@ public class AVM2SourceGenerator implements SourceGenerator { if (finallyEx > -1) { List preCatches = new ArrayList<>(); preCatches.add(0, new ExceptionMarkAVM2Instruction(finallyEx, MARK_E_TARGET)); - preCatches.add(ins(new GetLocal0Ins())); - preCatches.add(ins(new PushScopeIns())); - preCatches.add(AssignableAVM2Item.generateGetLoc(localData.activationReg)); - preCatches.add(ins(new PushScopeIns())); + for (GraphTargetItem s : localData.scopeStack) { + preCatches.addAll(toInsList(s.toSource(localData, this))); + if (s instanceof WithObjectAVM2Item) { + preCatches.add(ins(new PushWithIns())); + } else { + preCatches.add(ins(new PushScopeIns())); + } + } preCatches.add(ins(new NewCatchIns(), finallyEx)); preCatches.addAll(toInsList(AssignableAVM2Item.dupSetTemp(localData, this, tempReg))); preCatches.add(ins(new PushScopeIns())); @@ -769,7 +831,7 @@ public class AVM2SourceGenerator implements SourceGenerator { } ret.addAll(catches); - localData.exceptions.addAll(newex); + //localData.exceptions.addAll(newex); if (finallyEx > -1) { localData.finallyCatches.remove(localData.finallyCatches.size() - 1); @@ -1192,8 +1254,14 @@ public class AVM2SourceGenerator implements SourceGenerator { public int method(List callStack, String 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); - int oldActivationReg = localData.activationReg; + //calcRegisters(localData,needsActivation,paramNames,subvariables,body, hasArgs); + SourceGeneratorLocalData newlocalData = new SourceGeneratorLocalData(new HashMap(), 1, true, 0); + newlocalData.currentClass = className; + newlocalData.pkg = localData.pkg; + newlocalData.callStack.addAll(localData.callStack); + newlocalData.traitUsages = localData.traitUsages; + localData = newlocalData; + localData.activationReg = 0; for (int i = 0; i < subvariables.size(); i++) { @@ -1221,8 +1289,11 @@ public class AVM2SourceGenerator implements SourceGenerator { List registerNames = new ArrayList<>(); List registerTypes = new ArrayList<>(); if (className != null) { - registerTypes.add(pkg.isEmpty() ? className : pkg + "." + className); + String fullClassName = pkg.isEmpty() ? className : pkg + "." + className; + registerTypes.add(fullClassName); + localData.scopeStack.add(new LocalRegAVM2Item(null, registerNames.size(), null)); registerNames.add("this"); + } else { registerTypes.add("*"); registerNames.add("--nothis"); @@ -1251,6 +1322,7 @@ public class AVM2SourceGenerator implements SourceGenerator { registerNames.add("+$activation"); localData.activationReg = registerNames.size() - 1; registerTypes.add("Object"); + localData.scopeStack.add(new LocalRegAVM2Item(null, localData.activationReg, null)); } for (AssignableAVM2Item an : subvariables) { if (an instanceof NameAVM2Item) { @@ -1511,8 +1583,6 @@ public class AVM2SourceGenerator implements SourceGenerator { mbody.autoFillStats(abc, initScope); abc.addMethodBody(mbody); - localData.callStack.remove(mbody); - localData.activationReg = oldActivationReg; return mbody.method_info; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java index 03c291b30..9c1b8000b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java @@ -865,6 +865,7 @@ public class ActionScriptParser { openedNamespaces.add(abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE /*FIXME?*/, abc.constants.getStringId(ns.toString(), true)), 0, true)); break; case WITH: + needsActivation.setVal(true); expectedType(SymbolType.PARENT_OPEN); GraphTargetItem wvar = expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables);//(name(false, openedNamespaces, registerVars, inFunction, inMethod, variables)); if (!isNameOrProp(wvar)) { @@ -872,9 +873,18 @@ public class ActionScriptParser { } expectedType(SymbolType.PARENT_CLOSE); expectedType(SymbolType.CURLY_OPEN); - List wcmd = commands(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables); + List withVars = new ArrayList<>(); + List wcmd = commands(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, withVars); + variables.addAll(withVars); + for (AssignableAVM2Item a : withVars) { + if (a instanceof UnresolvedAVM2Item) { + UnresolvedAVM2Item ua = (UnresolvedAVM2Item) a; + ua.scopeStack.add(0, wvar); + } + } expectedType(SymbolType.CURLY_CLOSE); ret = new WithAVM2Item(null, wvar, wcmd); + ((WithAVM2Item) ret).subvariables = withVars; break; /*case DELETE: GraphTargetItem varDel = expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables);//name(false, openedNamespaces, registerVars, inFunction, inMethod, variables); @@ -1176,6 +1186,7 @@ public class ActionScriptParser { List> catchCommands = new ArrayList<>(); List catchExceptions = new ArrayList<>(); int varCnt = variables.size(); + List> catchesVars = new ArrayList<>(); while (s.type == SymbolType.CATCH) { expectedType(SymbolType.PARENT_OPEN); s = lex(); @@ -1188,10 +1199,30 @@ public class ActionScriptParser { variables.add(e); catchExceptions.add(e); e.setSlotNumber(1); - e.setSlotScope(2); //? + e.setSlotScope(Integer.MAX_VALUE); //will be changed later expectedType(SymbolType.PARENT_CLOSE); List cc = new ArrayList<>(); - cc.add(command(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)); + List catchVars = new ArrayList<>(); + cc.add(command(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, catchVars)); + catchesVars.add(catchVars); + variables.addAll(catchVars); + + for (AssignableAVM2Item a : catchVars) { + if (a instanceof UnresolvedAVM2Item) { + UnresolvedAVM2Item ui = (UnresolvedAVM2Item) a; + if (ui.getVariableName().equals(e.getVariableName())) { + try { + ui.resolve(new ArrayList(), new ArrayList(), abc, otherABCs, new ArrayList(), variables); + } catch (CompilationException ex) { + //ignore + } + ui.setSlotNumber(e.getSlotNumber()); + ui.setSlotScope(e.getSlotScope()); + } + + } + } + catchCommands.add(cc); s = lex(); found = true; @@ -1227,6 +1258,7 @@ public class ActionScriptParser { } lexer.pushback(s); TryAVM2Item tai = new TryAVM2Item(tryCommands, null, catchCommands, finallyCommands); + tai.catchVariables = catchesVars; tai.catchExceptions2 = catchExceptions; ret = tai; break; @@ -1496,6 +1528,9 @@ public class ActionScriptParser { } private boolean isNameOrProp(GraphTargetItem item) { + if (item instanceof UnresolvedAVM2Item) { + return true; //we don't know yet + } if (item instanceof NameAVM2Item) { return true; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java index 6c5c7b109..dfe9777a3 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java @@ -62,6 +62,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { public GraphTargetItem index; private List openedNamespaces; private List callStack; + public List scopeStack = new ArrayList(); @Override public AssignableAVM2Item copy() { @@ -96,113 +97,154 @@ public class PropertyAVM2Item extends AssignableAVM2Item { String objType = object == null ? null : object.returnType().toString(); String propType = ""; int propIndex = 0; - if (objType == null) { + if (scopeStack.isEmpty()) { //Everything is multiname when with command + if (objType == null) { - for (MethodBody b : callStack) { - for (int i = 0; i < b.traits.traits.size(); i++) { - Trait t = b.traits.traits.get(i); - if (t.getName(abc).getName(abc.constants, new ArrayList()).equals(propertyName)) { - if (t instanceof TraitSlotConst) { - TraitSlotConst tsc = (TraitSlotConst) t; - objType = "Function"; - propType = tsc.type_index == 0 ? "*" : abc.constants.constant_multiname.get(tsc.type_index).getNameWithNamespace(abc.constants); - propIndex = tsc.name_index; - if (!localData.traitUsages.containsKey(b)) { - localData.traitUsages.put(b, new ArrayList()); + /*for (GraphTargetItem s : scopeStack) { + String oType = s.returnType().toString(); + String name = oType; + String nsname = ""; + if(name.contains(".")){ + nsname = name.substring(0,name.lastIndexOf(".")); + name = name.substring(name.lastIndexOf(".")+1); + } + + List abcs = new ArrayList<>(); + abcs.add(abc); + abcs.addAll(otherABCs); + loopabc: + for (ABC a : abcs) { + for (int h = 0; h < a.instance_info.size(); h++) { + InstanceInfo ii = a.instance_info.get(h); + Multiname n = a.constants.constant_multiname.get(ii.name_index); + if (name.equals(n.getName(a.constants, new ArrayList())) && n.getNamespace(a.constants).hasName(nsname,a.constants)) { + Reference outName = new Reference<>(""); + Reference outNs = new Reference<>(""); + Reference outPropNs = new Reference<>(""); + Reference outPropNsKind = new Reference<>(1); + Reference outPropType = new Reference<>(""); + if (AVM2SourceGenerator.searchPrototypeChain(false, abcs, nsname, name, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType)) { + objType = "".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 + ); + + break loopabc; + } + } + } + } + }*/ + } + if (objType == null) { + for (MethodBody b : callStack) { + for (int i = 0; i < b.traits.traits.size(); i++) { + Trait t = b.traits.traits.get(i); + if (t.getName(abc).getName(abc.constants, new ArrayList()).equals(propertyName)) { + if (t instanceof TraitSlotConst) { + TraitSlotConst tsc = (TraitSlotConst) t; + objType = "Function"; + propType = tsc.type_index == 0 ? "*" : abc.constants.constant_multiname.get(tsc.type_index).getNameWithNamespace(abc.constants); + propIndex = tsc.name_index; + if (!localData.traitUsages.containsKey(b)) { + localData.traitUsages.put(b, new ArrayList()); + } + localData.traitUsages.get(b).add(i); } - localData.traitUsages.get(b).add(i); } } } - } - if (objType == null) { - loopobjType: - for (int i = 0; i < openedNamespaces.size(); i++) { - int nsindex = openedNamespaces.get(i); - int nsKind = abc.constants.constant_namespace.get(openedNamespaces.get(i)).kind; - String nsname = abc.constants.constant_namespace.get(openedNamespaces.get(i)).getName(abc.constants); - int name_index = 0; - for (int m = 1; m < abc.constants.constant_multiname.size(); m++) { - Multiname mname = abc.constants.constant_multiname.get(m); - if (mname.kind == Multiname.QNAME && mname.getName(abc.constants, new ArrayList()).equals(propertyName) && mname.namespace_index == nsindex) { - name_index = m; - break; - } - } - if (name_index > 0) { - for (int c = 0; c < abc.instance_info.size(); c++) { - for (Trait t : abc.instance_info.get(c).instance_traits.traits) { - if (t.name_index == name_index) { - objType = abc.instance_info.get(c).getName(abc.constants).getNameWithNamespace(abc.constants); - propType = AVM2SourceGenerator.getTraitReturnType(abc, t).toString(); - propIndex = t.name_index; - break loopobjType; - } - } - for (Trait t : abc.class_info.get(c).static_traits.traits) { - if (t.name_index == name_index) { - objType = abc.instance_info.get(c).getName(abc.constants).getNameWithNamespace(abc.constants); - propType = AVM2SourceGenerator.getTraitReturnType(abc, t).toString(); - propIndex = t.name_index; - break loopobjType; - } + if (objType == null) { + loopobjType: + for (int i = 0; i < openedNamespaces.size(); i++) { + int nsindex = openedNamespaces.get(i); + int nsKind = abc.constants.constant_namespace.get(openedNamespaces.get(i)).kind; + String nsname = abc.constants.constant_namespace.get(openedNamespaces.get(i)).getName(abc.constants); + int name_index = 0; + for (int m = 1; m < abc.constants.constant_multiname.size(); m++) { + Multiname mname = abc.constants.constant_multiname.get(m); + if (mname.kind == Multiname.QNAME && mname.getName(abc.constants, new ArrayList()).equals(propertyName) && mname.namespace_index == nsindex) { + name_index = m; + break; } } - } - if (nsKind == Namespace.KIND_PACKAGE) { - List abcs = new ArrayList<>(); - abcs.add(abc); - abcs.addAll(otherABCs); - loopabc: - for (ABC a : otherABCs) { - for (int h = 0; h < a.instance_info.size(); h++) { - InstanceInfo ii = a.instance_info.get(h); - 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 outPropType = new Reference<>(""); - if (AVM2SourceGenerator.searchPrototypeChain(false, abcs, nsname, n.getName(a.constants, new ArrayList()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType)) { - objType = "".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 - ); - + if (name_index > 0) { + for (int c = 0; c < abc.instance_info.size(); c++) { + for (Trait t : abc.instance_info.get(c).instance_traits.traits) { + if (t.name_index == name_index) { + objType = abc.instance_info.get(c).getName(abc.constants).getNameWithNamespace(abc.constants); + propType = AVM2SourceGenerator.getTraitReturnType(abc, t).toString(); + propIndex = t.name_index; break loopobjType; } } + for (Trait t : abc.class_info.get(c).static_traits.traits) { + if (t.name_index == name_index) { + objType = abc.instance_info.get(c).getName(abc.constants).getNameWithNamespace(abc.constants); + propType = AVM2SourceGenerator.getTraitReturnType(abc, t).toString(); + propIndex = t.name_index; + break loopobjType; + } + } + } + } + if (nsKind == Namespace.KIND_PACKAGE) { + List abcs = new ArrayList<>(); + abcs.add(abc); + abcs.addAll(otherABCs); + loopabc: + for (ABC a : otherABCs) { + for (int h = 0; h < a.instance_info.size(); h++) { + InstanceInfo ii = a.instance_info.get(h); + 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 outPropType = new Reference<>(""); + if (AVM2SourceGenerator.searchPrototypeChain(false, abcs, nsname, n.getName(a.constants, new ArrayList()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType)) { + objType = "".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 + ); + + break loopobjType; + } + } + } } } } } - } - } else { - List abcs = new ArrayList<>(); - abcs.add(abc); - abcs.addAll(otherABCs); - loopa: - for (ABC a : abcs) { - for (InstanceInfo ii : a.instance_info) { - Multiname m = ii.getName(a.constants); - if (m.getNameWithNamespace(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<>(""); - if (AVM2SourceGenerator.searchPrototypeChain(false, abcs, m.getNamespace(a.constants).getName(a.constants), m.getName(a.constants, new ArrayList()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType)) { - objType = "".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 - ); + } else { + List abcs = new ArrayList<>(); + abcs.add(abc); + abcs.addAll(otherABCs); + loopa: + for (ABC a : abcs) { + for (InstanceInfo ii : a.instance_info) { + Multiname m = ii.getName(a.constants); + if (m.getNameWithNamespace(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<>(""); + if (AVM2SourceGenerator.searchPrototypeChain(false, abcs, m.getNamespace(a.constants).getName(a.constants), m.getName(a.constants, new ArrayList()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType)) { + objType = "".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 + ); - break loopa; + break loopa; + } } } } @@ -459,7 +501,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { String cname; String pkgName = ""; cname = localData.currentClass; - if (cname.contains(".")) { + if (cname != null && cname.contains(".")) { pkgName = cname.substring(0, cname.lastIndexOf('.')); cname = cname.substring(cname.lastIndexOf('.') + 1); } @@ -471,7 +513,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { List abcs = new ArrayList<>(); abcs.add(abc); abcs.addAll(otherABCs); - if (AVM2SourceGenerator.searchPrototypeChain(true, abcs, pkgName, cname, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType)) { + if (cname != null && AVM2SourceGenerator.searchPrototypeChain(true, abcs, pkgName, cname, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType)) { NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.currentClass), 0, "this", null, false, openedNamespaces); nobj.setRegNumber(0); obj = nobj; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java index 8b8627435..87352de85 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java @@ -58,6 +58,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { public GraphTargetItem resolved; private boolean mustBeType; public List importedClasses; + public List scopeStack = new ArrayList(); @Override public AssignableAVM2Item copy() { @@ -302,33 +303,35 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { return resolved; } - //search for variable - for (AssignableAVM2Item a : variables) { - if (a instanceof NameAVM2Item) { - NameAVM2Item n = (NameAVM2Item) a; - if (n.isDefinition() && parts.get(0).equals(n.getVariableName())) { - NameAVM2Item ret = new NameAVM2Item(n.type, n.line, parts.get(0), null, false, openedNamespaces); - ret.setSlotScope(n.getSlotScope()); - ret.setSlotNumber(n.getSlotNumber()); - ret.setRegNumber(n.getRegNumber()); - resolved = ret; - for (int i = 1; i < parts.size(); i++) { - resolved = new PropertyAVM2Item(resolved, parts.get(i), null, abc, otherAbcs, openedNamespaces, new ArrayList()); - if (i == parts.size() - 1) { - ((PropertyAVM2Item) resolved).index = index; - ((PropertyAVM2Item) resolved).assignedValue = assignedValue; + if (scopeStack.isEmpty()) { //Everything is multiname property in with command + + //search for variable + for (AssignableAVM2Item a : variables) { + if (a instanceof NameAVM2Item) { + NameAVM2Item n = (NameAVM2Item) a; + if (n.isDefinition() && parts.get(0).equals(n.getVariableName())) { + NameAVM2Item ret = new NameAVM2Item(n.type, n.line, parts.get(0), null, false, openedNamespaces); + ret.setSlotScope(n.getSlotScope()); + ret.setSlotNumber(n.getSlotNumber()); + ret.setRegNumber(n.getRegNumber()); + resolved = ret; + for (int i = 1; i < parts.size(); i++) { + resolved = new PropertyAVM2Item(resolved, parts.get(i), null, abc, otherAbcs, openedNamespaces, new ArrayList()); + if (i == parts.size() - 1) { + ((PropertyAVM2Item) resolved).index = index; + ((PropertyAVM2Item) resolved).assignedValue = assignedValue; + } } + if (parts.size() == 1) { + ret.setIndex(index); + ret.setAssignedValue(assignedValue); + } + ret.setNs(n.getNs()); + return ret; } - if (parts.size() == 1) { - ret.setIndex(index); - ret.setAssignedValue(assignedValue); - } - ret.setNs(n.getNs()); - return ret; } } } - //Search for types in imported classes for (String imp : importedClasses) { String impName = imp; @@ -415,6 +418,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { for (int i = 0; i < parts.size(); i++) { resolved = new PropertyAVM2Item(resolved, parts.get(i), (i == parts.size() - 1) ? index : null, abc, otherAbcs, openedNamespaces, callStack); if (ret == null) { + ((PropertyAVM2Item) resolved).scopeStack = scopeStack; ret = resolved; } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/todo.txt b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/todo.txt index 3539689b2..784f23c23 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/todo.txt +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/todo.txt @@ -2,8 +2,6 @@ TODO List for AS3 parser/compiler: ------------------------------ - E4X (XML) - typenames (Vectors) -- with -- try/catch scopes (with, inner functions - no this) - inner function names - delete property - default xml namespace