diff --git a/.travis.yml b/.travis.yml index 5a833f01d..b7cc25a4f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: java -jdk: [oraclejdk9] +jdk: [openjdk8] #dist: trusty addons: apt: diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dbc0a23a..0494eaeda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,37 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Added +- Display object depth in flash panel +- Show imported files on script import, able to cancel import +- [#270] AS3 show progress on deofuscating p-code +- [#1718] Show progress on injecting debug info / SWD generation (before Debugging) + +### Changed +- [#1801] - Flex SDK links to Apache Flex + ### Fixed +- [#1761] AS3 - try..finally inside another structure like if +- [#1762] AS call on integer numbers parenthesis +- [#1762] AS3 - Auto adding returnvoid/return undefined +- [#1762] AS - switch detection (mostcommon pathpart) +- [#1763] AS3 - initialization of activation object in some cases +- AS3 - direct editation - arguments object on method with activation +- AS3 - direct editation - bit not +- AS3 - direct editation - call on local register +- AS3 - direct editation - resolve properties and local regs before types +- AS3 - direct editation - call on index +- Incorrect position in Flash Player preview and SWF export +- AS1/2 actioncontainers (like try) inside ifs +- AS1/2 switch detection +- [#1766] AS3 - direct editation - namespaces on global level without leading colon +- [#1763] AS3 - function with activation - param assignment is not a declaration +- AS3 - insert debug instruction to mark register names even with activation +- AS3 - debugging in inner functions +- AS1/2 - debugger - rewinding playback to apply breakpoints +- [#1773] - Auto set flagWideCodes on FontInfo wide character adding +- [#1769] - Do not mark getter+setter as colliding (#xxx suffix) +- [#1801] - Flex SDK not required on commandline when Flex compilation is disabled - Multiname - performance issues ## [15.0.0] - 2021-11-29 @@ -2198,6 +2228,10 @@ All notable changes to this project will be documented in this file. ### Added - Initial public release +[Unreleased]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version15.0.0...dev +[15.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version14.6.0...version15.0.0 +[14.6.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version14.5.2...version14.6.0 +[14.5.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version14.5.1...version14.5.2 [14.5.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version14.5.0...version14.5.1 [14.5.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version14.4.0...version14.5.0 [14.4.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version14.3.1...version14.4.0 @@ -2313,6 +2347,15 @@ All notable changes to this project will be documented in this file. [alpha 9]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha8...alpha9 [alpha 8]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha7...alpha8 [alpha 7]: https://github.com/jindrapetrik/jpexs-decompiler/releases/tag/alpha7 +[#270]: https://www.free-decompiler.com/flash/issues/270 +[#1718]: https://www.free-decompiler.com/flash/issues/1718 +[#1761]: https://www.free-decompiler.com/flash/issues/1761 +[#1762]: https://www.free-decompiler.com/flash/issues/1762 +[#1763]: https://www.free-decompiler.com/flash/issues/1763 +[#1766]: https://www.free-decompiler.com/flash/issues/1766 +[#1773]: https://www.free-decompiler.com/flash/issues/1773 +[#1769]: https://www.free-decompiler.com/flash/issues/1769 +[#1801]: https://www.free-decompiler.com/flash/issues/1801 [#1750]: https://www.free-decompiler.com/flash/issues/1750 [#1485]: https://www.free-decompiler.com/flash/issues/1485 [#1681]: https://www.free-decompiler.com/flash/issues/1681 @@ -2345,7 +2388,6 @@ All notable changes to this project will be documented in this file. [#1488]: https://www.free-decompiler.com/flash/issues/1488 [#1584]: https://www.free-decompiler.com/flash/issues/1584 [#1572]: https://www.free-decompiler.com/flash/issues/1572 -[#270]: https://www.free-decompiler.com/flash/issues/270 [#1645]: https://www.free-decompiler.com/flash/issues/1645 [#1639]: https://www.free-decompiler.com/flash/issues/1639 [#1371]: https://www.free-decompiler.com/flash/issues/1371 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DeobfuscationListener.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DeobfuscationListener.java new file mode 100644 index 000000000..3abed2bc1 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DeobfuscationListener.java @@ -0,0 +1,9 @@ +package com.jpexs.decompiler.flash; + +/** + * + * @author JPEXS + */ +public interface DeobfuscationListener { + public void itemDeobfuscated(); +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/FinalProcessLocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/FinalProcessLocalData.java index e39342e1a..d129f4959 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/FinalProcessLocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/FinalProcessLocalData.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash; import com.jpexs.decompiler.graph.Loop; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index c6fc16021..419b8b799 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -168,6 +168,7 @@ import com.jpexs.helpers.Helper; import com.jpexs.helpers.ImmediateFuture; import com.jpexs.helpers.NulStream; import com.jpexs.helpers.ProgressListener; +import com.jpexs.helpers.Reference; import com.jpexs.helpers.SerializableImage; import com.jpexs.helpers.utf8.Utf8Helper; import java.awt.AlphaComposite; @@ -1949,7 +1950,7 @@ public final class SWF implements SWFContainerItem, Timelined { } } - protected void informListeners(String event, Object data) { + public void informListeners(String event, Object data) { for (EventListener listener : listeners) { listener.handleEvent(event, data); } @@ -3353,13 +3354,24 @@ public final class SWF implements SWFContainerItem, Timelined { public void deobfuscate(DeobfuscationLevel level) throws InterruptedException { List atags = getAbcList(); + int apos = 0; for (ABCContainerTag tag : atags) { + apos++; + final int fpos = apos; + Reference numDeoScripts = new Reference<>(0); + DeobfuscationListener deoListener = new DeobfuscationListener() { + @Override + public void itemDeobfuscated() { + numDeoScripts.setVal(numDeoScripts.getVal() + 1); + informListeners("deobfuscate_pcode", "abc " + fpos + "/" + atags.size() + " script " + numDeoScripts.getVal() + "/" + tag.getABC().script_info.size()); + } + }; if (level == DeobfuscationLevel.LEVEL_REMOVE_DEAD_CODE) { - tag.getABC().removeDeadCode(); + tag.getABC().removeDeadCode(deoListener); } else if (level == DeobfuscationLevel.LEVEL_REMOVE_TRAPS) { - tag.getABC().removeTraps(); + tag.getABC().removeTraps(deoListener); } else if (level == DeobfuscationLevel.LEVEL_RESTORE_CONTROL_FLOW) { - tag.getABC().removeTraps(); + tag.getABC().removeTraps(deoListener); } ((Tag) tag).setModified(true); @@ -3374,14 +3386,14 @@ public final class SWF implements SWFContainerItem, Timelined { * @param decompileDir Directory to virtual decompile (will affect * debugfile) */ - public void enableDebugging(boolean injectAS3Code, File decompileDir) { + public void enableDebugging(boolean injectAS3Code, File decompileDir) throws InterruptedException { enableDebugging(injectAS3Code, decompileDir, false); } /** * Enables debugging. Adds tags to enable debugging. */ - public void enableDebugging() { + public void enableDebugging() throws InterruptedException { enableDebugging(false, null, false); } @@ -3394,7 +3406,7 @@ public final class SWF implements SWFContainerItem, Timelined { * debugfile) * @param telemetry Enable telemetry info? */ - public void enableDebugging(boolean injectAS3Code, File decompileDir, boolean telemetry) { + public void enableDebugging(boolean injectAS3Code, File decompileDir, boolean telemetry) throws InterruptedException { enableDebugging(injectAS3Code, decompileDir, telemetry, false); } @@ -3402,9 +3414,15 @@ public final class SWF implements SWFContainerItem, Timelined { * Injects debugline and debugfile instructions to AS3 P-code (lines of * P-code) */ - public void injectAS3PcodeDebugInfo() { + public void injectAS3PcodeDebugInfo() throws InterruptedException { List packs = getAS3Packs(); + int i = 0; for (ScriptPack s : packs) { + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException(); + } + i++; + informListeners("inject_debuginfo", "" + i + "/" + packs.size() + ": " + s.getPath()); int abcIndex = s.allABCs.indexOf(s.abc); if (s.isSimple) { s.injectPCodeDebugInfo(abcIndex); @@ -3417,9 +3435,15 @@ public final class SWF implements SWFContainerItem, Timelined { * * @param decompileDir Directory to set file information paths */ - public void injectAS3DebugInfo(File decompileDir) { + public void injectAS3DebugInfo(File decompileDir) throws InterruptedException { List packs = getAS3Packs(); + int i = 0; for (ScriptPack s : packs) { + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException(); + } + i++; + informListeners("inject_debuginfo", "" + i + "/" + packs.size() + ": " + s.getPath()); if (s.isSimple) { s.injectDebugInfo(decompileDir); } @@ -3436,7 +3460,7 @@ public final class SWF implements SWFContainerItem, Timelined { * @param telemetry Enable telemetry info? * @param pcodeLevel inject Pcode lines instead of decompiled lines */ - public void enableDebugging(boolean injectAS3Code, File decompileDir, boolean telemetry, boolean pcodeLevel) { + public void enableDebugging(boolean injectAS3Code, File decompileDir, boolean telemetry, boolean pcodeLevel) throws InterruptedException { if (injectAS3Code) { if (pcodeLevel) { @@ -3520,7 +3544,7 @@ public final class SWF implements SWFContainerItem, Timelined { return r; } - public boolean generatePCodeSwdFile(File file, Map> breakpoints) throws IOException { + public boolean generatePCodeSwdFile(File file, Map> breakpoints) throws IOException, InterruptedException { DebugIDTag dit = getDebugId(); if (dit == null) { return false; @@ -3540,6 +3564,10 @@ public final class SWF implements SWFContainerItem, Timelined { List names = new ArrayList<>(asms.keySet()); Collections.sort(names); for (String name : names) { + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException(); + } + informListeners("generate_swd", name); moduleId++; String sname = "#PCODE " + name; int bitmap = SWD.bitmapAction; @@ -3611,6 +3639,10 @@ public final class SWF implements SWFContainerItem, Timelined { List names = new ArrayList<>(asms.keySet()); Collections.sort(names); for (String name : names) { + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException(); + } + informListeners("generate_swd", name); List regitems = new ArrayList<>(); moduleId++; HighlightedText cs; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java index 93fe40a57..e6b9b9f4e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java @@ -16,6 +16,7 @@ */ package com.jpexs.decompiler.flash.abc; +import com.jpexs.decompiler.flash.DeobfuscationListener; import com.jpexs.decompiler.flash.EndOfStreamException; import com.jpexs.decompiler.flash.EventListener; import com.jpexs.decompiler.flash.SWF; @@ -232,14 +233,24 @@ public class ABC { } public int removeTraps() throws InterruptedException { + return removeTraps(null); + } + public int removeTraps(DeobfuscationListener listener) throws InterruptedException { int rem = 0; for (int s = 0; s < script_info.size(); s++) { rem += script_info.get(s).removeTraps(s, this, ""); + if (listener != null) { + listener.itemDeobfuscated(); + } } return rem; } public int removeDeadCode() throws InterruptedException { + return removeDeadCode(null); + } + + public int removeDeadCode(DeobfuscationListener listener) throws InterruptedException { int rem = 0; for (MethodBody body : bodies) { rem += body.removeDeadCode(constants, null/*FIXME*/, method_info.get(body.method_info)); 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 79b09b09b..950c7998e 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 @@ -423,7 +423,7 @@ public class ScriptPack extends AS3ClassTreeItem { Trait trait = abc.findTraitByTraitId(classIndex, traitIndex); if (((trait instanceof TraitMethodGetterSetter) && (((TraitMethodGetterSetter) trait).method_info != methodIndex)) || ((trait instanceof TraitFunction) && (((TraitFunction) trait).method_info != methodIndex))) { - continue; //inner anonymous function - ignore. TODO: make work + //continue; //inner anonymous function - ignore. TODO: make work } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 49d9c28ed..d3e26f2c7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -248,8 +248,10 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.DXNSIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.DXNSLateIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.EscXAttrIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.EscXElemIns; +import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.CoerceAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ConvertAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.InitPropertyAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; @@ -1861,7 +1863,7 @@ public class AVM2Code implements Cloneable { return assignment; } - private void injectDeclarations(List items, int minreg, DeclarationAVM2Item[] declaredRegisters, List declaredSlots, List declaredSlotsDec, ABC abc, MethodBody body) { + private void injectDeclarations(List paramNames, List items, int minreg, DeclarationAVM2Item[] declaredRegisters, List declaredSlots, List declaredSlotsDec, List declaredProperties, List declaredPropsDec, ABC abc, MethodBody body) { for (int i = 0; i < items.size(); i++) { GraphTargetItem currentItem = items.get(i); List itemsOnLine = new ArrayList<>(); @@ -1905,35 +1907,72 @@ public class AVM2Code implements Cloneable { } } } + if (subItem instanceof SetPropertyAVM2Item) { + SetPropertyAVM2Item sp = (SetPropertyAVM2Item) subItem; + if (sp.object instanceof FindPropertyAVM2Item) { + if (sp.propertyName instanceof FullMultinameAVM2Item) { + FullMultinameAVM2Item propName = (FullMultinameAVM2Item) sp.propertyName; + if (!paramNames.contains(propName.resolvedMultinameName)) { + if (!declaredProperties.contains(propName.resolvedMultinameName)) { + for (int t = 0; t < body.traits.traits.size(); t++) { + if (body.traits.traits.get(t).getName(abc).getName(abc.constants, new ArrayList(), true, false) + .equals(propName.resolvedMultinameName)) { + if (body.traits.traits.get(t) instanceof TraitSlotConst) { + GraphTargetItem type = PropertyAVM2Item.multinameToType(((TraitSlotConst) body.traits.traits.get(t)).type_index, abc.constants); + DeclarationAVM2Item d = new DeclarationAVM2Item(subItem, type); + sp.setDeclaration(d); + declaredPropsDec.add(d); + declaredProperties.add(propName.resolvedMultinameName); + if (subItem == currentItem) { + items.set(i, d); + } else { + d.showValue = false; + items.add(i, d); + i++; + } + } + } + } + } else { + int idx = declaredProperties.indexOf(propName.resolvedMultinameName); + sp.setDeclaration(declaredPropsDec.get(idx)); + } + } + } + } + } if (subItem instanceof SetSlotAVM2Item) { SetSlotAVM2Item ssti = (SetSlotAVM2Item) subItem; if (ssti.scope instanceof NewActivationAVM2Item) { Slot sl = new Slot(ssti.scope, ssti.slotName); - if (!declaredSlots.contains(sl)) { - GraphTargetItem type = TypeItem.UNBOUNDED; - for (int t = 0; t < body.traits.traits.size(); t++) { - if (body.traits.traits.get(t).getName(abc) == sl.multiname) { - if (body.traits.traits.get(t) instanceof TraitSlotConst) { - type = PropertyAVM2Item.multinameToType(((TraitSlotConst) body.traits.traits.get(t)).type_index, abc.constants); + if (!paramNames.contains(sl.multiname.getName(abc.constants, new ArrayList<>(), true, false))) { + + if (!declaredSlots.contains(sl)) { + GraphTargetItem type = TypeItem.UNBOUNDED; + for (int t = 0; t < body.traits.traits.size(); t++) { + if (body.traits.traits.get(t).getName(abc) == sl.multiname) { + if (body.traits.traits.get(t) instanceof TraitSlotConst) { + type = PropertyAVM2Item.multinameToType(((TraitSlotConst) body.traits.traits.get(t)).type_index, abc.constants); + } } } - } - DeclarationAVM2Item d = new DeclarationAVM2Item(subItem, type); - ssti.setDeclaration(d); - declaredSlotsDec.add(d); - declaredSlots.add(sl); + DeclarationAVM2Item d = new DeclarationAVM2Item(subItem, type); + ssti.setDeclaration(d); + declaredSlotsDec.add(d); + declaredSlots.add(sl); + + if (subItem == currentItem) { + items.set(i, d); + } else { + d.showValue = false; + items.add(i, d); + i++; + } - if (subItem == currentItem) { - items.set(i, d); } else { - d.showValue = false; - items.add(i, d); - i++; + int idx = declaredSlots.indexOf(sl); + ssti.setDeclaration(declaredSlotsDec.get(idx)); } - - } else { - int idx = declaredSlots.indexOf(sl); - ssti.setDeclaration(declaredSlotsDec.get(idx)); } } } @@ -1942,7 +1981,7 @@ public class AVM2Code implements Cloneable { if (currentItem instanceof Block) { Block blk = (Block) currentItem; for (List sub : blk.getSubs()) { - injectDeclarations(sub, minreg, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); + injectDeclarations(paramNames, sub, minreg, declaredRegisters, declaredSlots, declaredSlotsDec, declaredProperties, declaredPropsDec, abc, body); } } } @@ -2088,7 +2127,12 @@ public class AVM2Code implements Cloneable { // //int minreg = abc.method_info.get(body.method_info).getMaxReservedReg() + 1; - injectDeclarations(list, 1, d, new ArrayList<>(), new ArrayList<>(), abc, body); + HashMap registerNames = body.getLocalRegNames(abc); + List paramNamesList = new ArrayList<>(); + for (int ir = 0; ir < r; ir++) { + paramNamesList.add(AVM2Item.localRegName(localRegNames, ir)); + } + injectDeclarations(paramNamesList, list, 1, d, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), abc, body); int lastPos = list.size() - 1; if (lastPos < 0) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2FinalProcessLocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2FinalProcessLocalData.java new file mode 100644 index 000000000..941f76f88 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2FinalProcessLocalData.java @@ -0,0 +1,21 @@ +package com.jpexs.decompiler.flash.abc.avm2; + +import com.jpexs.decompiler.flash.FinalProcessLocalData; +import com.jpexs.decompiler.graph.Loop; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class AVM2FinalProcessLocalData extends FinalProcessLocalData { + + public HashMap localRegNames; + + public AVM2FinalProcessLocalData(List loops, HashMap localRegNames) { + super(loops); + this.localRegNames = localRegNames; + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index b8d1e7785..c211c9b53 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.FinalProcessLocalData; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.AVM2LocalData; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2FinalProcessLocalData; import com.jpexs.decompiler.flash.abc.avm2.CodeStats; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; @@ -46,6 +47,7 @@ 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.types.CoerceAIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertIIns; +import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ConstructAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FilteredCheckAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item; @@ -114,6 +116,7 @@ import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; @@ -462,15 +465,17 @@ public class AVM2Graph extends Graph { } } - //return in finally block is joined after switch decision - for (GraphPart p : switchPart.nextParts) { + //This caused problems, so it's commented out + //the tests still pass, so I can only wonder why it's there. :-( + //return in finally block is joined after switch decision + /*for (GraphPart p : switchPart.nextParts) { for (GraphPart r : p.refs) { if (r != switchPart) { localData.finallyJumps.put(r, p); localData.finallyJumpsToFinallyIndex.put(r, e); } } - } + }*/ localData.ignoredSwitches.put(e, switchPart); } else { @@ -1964,6 +1969,24 @@ public class AVM2Graph extends Graph { Map localRegNames = body.getLocalRegNames(abc); loopi: for (int i = 0; i < list.size(); i++) { + if (list.get(i) instanceof SetPropertyAVM2Item) { + SetPropertyAVM2Item sp = (SetPropertyAVM2Item) list.get(i); + if (sp.object instanceof FindPropertyAVM2Item) { + if (sp.propertyName instanceof FullMultinameAVM2Item) { + FullMultinameAVM2Item propName = (FullMultinameAVM2Item) sp.propertyName; + if (sp.value instanceof LocalRegAVM2Item) { + LocalRegAVM2Item lr = (LocalRegAVM2Item) sp.value; + AVM2FinalProcessLocalData aLocalData = (AVM2FinalProcessLocalData) localData; + if (Objects.equals(propName.resolvedMultinameName, AVM2Item.localRegName(aLocalData.localRegNames, lr.regIndex))) { + list.remove(i); + i--; + continue loopi; + } + } + + } + } + } if (list.get(i) instanceof SetSlotAVM2Item) { SetSlotAVM2Item sslot = (SetSlotAVM2Item) list.get(i); if (sslot.slotObject instanceof NewActivationAVM2Item) { @@ -2153,7 +2176,7 @@ public class AVM2Graph extends Graph { @Override protected FinalProcessLocalData getFinalData(BaseLocalData localData, List loops, List throwStates) { - FinalProcessLocalData finalProcess = super.getFinalData(localData, loops, throwStates); + FinalProcessLocalData finalProcess = new AVM2FinalProcessLocalData(loops, ((AVM2LocalData) localData).localRegNames); finalProcess.registerUsage = ((AVM2LocalData) localData).setLocalPosToGetLocalPos; return finalProcess; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java index 0750da5f0..ec2c55d89 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model; import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; @@ -89,7 +90,7 @@ public abstract class AVM2Item extends GraphTargetItem { } if (!empty && object != null) { - if (object.getPrecedence() > PRECEDENCE_PRIMARY) { + if (object.getPrecedence() > PRECEDENCE_PRIMARY || (object instanceof IntegerValueAVM2Item)) { writer.append("("); object.toString(writer, localData); writer.append(")"); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallMethodAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallMethodAVM2Item.java index e896b235f..c3e7d9ec9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallMethodAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallMethodAVM2Item.java @@ -52,7 +52,13 @@ public class CallMethodAVM2Item extends AVM2Item { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - receiver.toString(writer, localData); + if (receiver.getPrecedence() > getPrecedence() || (receiver instanceof IntegerValueAVM2Item)) { + writer.append("("); + receiver.toString(writer, localData); + writer.append(")"); + } else { + receiver.toString(writer, localData); + } writer.append("."); writer.append(methodName); writer.spaceBeforeCallParenthesies(arguments.size()); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallStaticAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallStaticAVM2Item.java index 47d0a9e0c..e0112ceec 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallStaticAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallStaticAVM2Item.java @@ -52,7 +52,13 @@ public class CallStaticAVM2Item extends AVM2Item { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - receiver.toString(writer, localData); + if (receiver.getPrecedence() > getPrecedence() || (receiver instanceof IntegerValueAVM2Item)) { + writer.append("("); + receiver.toString(writer, localData); + writer.append(")"); + } else { + receiver.toString(writer, localData); + } writer.append("."); writer.append(methodName); writer.spaceBeforeCallParenthesies(arguments.size()); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java index 3416ad192..c200570d8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java @@ -16,12 +16,15 @@ */ package com.jpexs.decompiler.flash.abc.avm2.model.clauses; +import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.CoerceAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ConvertAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.GetSlotAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.SetPropertyAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.SetSlotAVM2Item; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; @@ -148,6 +151,39 @@ public class DeclarationAVM2Item extends AVM2Item { } return writer; } + + if (assignment instanceof SetPropertyAVM2Item) { + SetPropertyAVM2Item spti = (SetPropertyAVM2Item) assignment; + HighlightData srcData = getSrcData(); + srcData.localName = ((FullMultinameAVM2Item) spti.propertyName).resolvedMultinameName; + srcData.declaration = true; + + GraphTargetItem val = spti.value; + GraphTargetItem coerType = TypeItem.UNBOUNDED; + if (spti.value instanceof CoerceAVM2Item) { + coerType = ((CoerceAVM2Item) spti.value).typeObj; + } + if (spti.value instanceof ConvertAVM2Item) { + coerType = ((ConvertAVM2Item) spti.value).type; + } + //strip coerce if its declared as this type + if (coerType.equals(type) && !coerType.equals(TypeItem.UNBOUNDED)) { + val = val.value; + } + + srcData.declaredType = (type instanceof TypeItem) ? ((TypeItem) type).fullTypeName : DottedChain.ALL; + writer.append("var "); + writer.append(IdentifiersDeobfuscation.printIdentifier(true, ((FullMultinameAVM2Item) spti.propertyName).resolvedMultinameName)); + writer.append(":"); + + type.appendTry(writer, localData); + if (showValue) { + writer.append(" = "); + val.toString(writer, localData); + } + return writer; + } + writer.append("var "); return assignment.toString(writer, localData); } 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 1d64d239d..5b94c9e12 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 @@ -1260,8 +1260,8 @@ public class AVM2SourceGenerator implements SourceGenerator { public void generateClass(List importedClasses, List cinitVariables, boolean cinitNeedsActivation, List cinit, List openedNamespaces, int namespace, int initScope, DottedChain pkg, ClassInfo classInfo, InstanceInfo instanceInfo, SourceGeneratorLocalData localData, boolean isInterface, String name, String superName, GraphTargetItem extendsVal, List implementsStr, GraphTargetItem iinit, List iinitVariables, boolean iinitNeedsActivation, List traitItems, Reference class_index) throws AVM2ParseException, CompilationException { localData.currentClass = name; localData.pkg = pkg; - localData.privateNs = abcIndex.getSelectedAbc().constants.getNamespaceId(Namespace.KIND_PRIVATE, pkg.toRawString() + ":" + name, 0, true); - localData.protectedNs = abcIndex.getSelectedAbc().constants.getNamespaceId(Namespace.KIND_PROTECTED, pkg.toRawString() + ":" + name, 0, true); + localData.privateNs = abcIndex.getSelectedAbc().constants.getNamespaceId(Namespace.KIND_PRIVATE, pkg.toRawString().isEmpty() ? name : pkg.toRawString() + ":" + name, 0, true); + localData.protectedNs = abcIndex.getSelectedAbc().constants.getNamespaceId(Namespace.KIND_PROTECTED, pkg.toRawString().isEmpty() ? name : pkg.toRawString() + ":" + name, 0, true); if (extendsVal == null && !isInterface) { extendsVal = new TypeItem(DottedChain.OBJECT); } @@ -1621,7 +1621,7 @@ public class AVM2SourceGenerator implements SourceGenerator { UnresolvedAVM2Item n = (UnresolvedAVM2Item) an; if (n.resolved == null) { String fullClass = localData.getFullClass(); - GraphTargetItem res = n.resolve(localData.currentClass, new TypeItem(fullClass), paramTypes, paramNames, abcIndex, callStack, subvariables); + GraphTargetItem res = n.resolve(localData, localData.currentClass, new TypeItem(fullClass), paramTypes, paramNames, abcIndex, callStack, subvariables); if (res instanceof AssignableAVM2Item) { subvariables.set(i, (AssignableAVM2Item) res); } else { @@ -1638,7 +1638,7 @@ public class AVM2SourceGenerator implements SourceGenerator { UnresolvedAVM2Item n = (UnresolvedAVM2Item) an; if (n.resolved == null) { String fullClass = localData.getFullClass(); - GraphTargetItem res = n.resolve(localData.currentClass, new TypeItem(fullClass), paramTypes, paramNames, abcIndex, callStack, subvariables); + GraphTargetItem res = n.resolve(localData, localData.currentClass, new TypeItem(fullClass), paramTypes, paramNames, abcIndex, callStack, subvariables); paramTypes.set(t, res); } } @@ -1689,8 +1689,10 @@ public class AVM2SourceGenerator implements SourceGenerator { NameAVM2Item n = (NameAVM2Item) an; if (n.getVariableName().equals("arguments") & !n.isDefinition()) { registerNames.add("arguments"); - registerTypes.add(new TypeItem("Object")); + registerTypes.add(new TypeItem("Array")); registerLines.add(0); //? + slotNames.add(n.getVariableName()); + slotTypes.add(new TypeItem("Array")); hasArguments = true; break; } @@ -1916,8 +1918,13 @@ public class AVM2SourceGenerator implements SourceGenerator { declarations.add(d); } } + boolean addRet = false; if (body != null) { body.addAll(0, declarations); + if (body.isEmpty() || (!((body.get(body.size() - 1) instanceof ReturnValueAVM2Item) + || (body.get(body.size() - 1) instanceof ReturnVoidAVM2Item)))) { + addRet = true; + } } localData.exceptions = new ArrayList<>(); @@ -1994,23 +2001,20 @@ public class AVM2SourceGenerator implements SourceGenerator { } } for (int i = 1; i < registerNames.size(); i++) { - if (!needsActivation) { - mbodyCode.add(i - 1, ins(AVM2Instructions.Debug, 1, str(registerNames.get(i)), i - 1, (int) registerLines.get(i))); - } + mbodyCode.add(i - 1, ins(AVM2Instructions.Debug, 1, str(registerNames.get(i)), i - 1, (int) registerLines.get(i))); } if (!subMethod) { mbodyCode.add(0, new AVM2Instruction(0, AVM2Instructions.GetLocal0, null)); mbodyCode.add(1, new AVM2Instruction(0, AVM2Instructions.PushScope, null)); } - boolean addRet = false; - if (!mbodyCode.isEmpty()) { + /*if (!mbodyCode.isEmpty()) { InstructionDefinition lastDef = mbodyCode.get(mbodyCode.size() - 1).definition; if (!((lastDef instanceof ReturnVoidIns) || (lastDef instanceof ReturnValueIns))) { addRet = true; } } else { addRet = true; - } + }*/ if (addRet) { if (retType.toString().equals("*") || retType.toString().equals("void") || constructor) { mbodyCode.add(new AVM2Instruction(0, AVM2Instructions.ReturnVoid, null)); @@ -2172,7 +2176,7 @@ public class AVM2SourceGenerator implements SourceGenerator { public int superIntName(SourceGeneratorLocalData localData, GraphTargetItem un) throws CompilationException { if (un instanceof UnresolvedAVM2Item) { - ((UnresolvedAVM2Item) un).resolve(localData.currentClass, null, new ArrayList<>(), new ArrayList<>(), abcIndex, new ArrayList<>(), new ArrayList<>()); + ((UnresolvedAVM2Item) un).resolve(localData, localData.currentClass, null, new ArrayList<>(), new ArrayList<>(), abcIndex, new ArrayList<>(), new ArrayList<>()); un = ((UnresolvedAVM2Item) un).resolved; } if (!(un instanceof TypeItem)) { //not applyType @@ -2606,31 +2610,34 @@ public class AVM2SourceGenerator implements SourceGenerator { return TypeItem.UNBOUNDED; } - public static boolean searchPrototypeChain(List otherNs, 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) { + public static boolean searchPrototypeChain(List otherNs, 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, Reference isType) { // private and protected namespaces first so we find overriding functions before overridden functions - if (searchPrototypeChain(privateNs, instanceOnly, abc, pkg, obj, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc)) { + if (searchPrototypeChain(privateNs, instanceOnly, abc, pkg, obj, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc, isType)) { return true; } - if (searchPrototypeChain(protectedNs, instanceOnly, abc, pkg, obj, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc)) { + if (searchPrototypeChain(protectedNs, instanceOnly, abc, pkg, obj, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc, isType)) { return true; } for (int ns : otherNs) { - if (searchPrototypeChain(ns, instanceOnly, abc, pkg, obj, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc)) { + if (searchPrototypeChain(ns, instanceOnly, abc, pkg, obj, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc, isType)) { return true; } } - return searchPrototypeChain(0, instanceOnly, abc, pkg, obj, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc); + return searchPrototypeChain(0, instanceOnly, abc, pkg, obj, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc, isType); } - 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) { - + 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, Reference isType) { + isType.setVal(false); AbcIndexing.TraitIndex sp = abc.findScriptProperty(pkg.addWithSuffix(propertyName)); if (sp == null) { sp = abc.findProperty(new AbcIndexing.PropertyDef(propertyName, new TypeItem(pkg.addWithSuffix(obj)), abc.getSelectedAbc(), selectedNs), !instanceOnly, true); } if (sp != null) { + if (sp.trait instanceof TraitClass) { + isType.setVal(true); + } if (sp.objType instanceof TypeItem) { outName.setVal(((TypeItem) sp.objType).fullTypeName.getLast()); outNs.setVal(((TypeItem) sp.objType).fullTypeName.getWithoutLast()); @@ -2712,7 +2719,7 @@ public class AVM2SourceGenerator implements SourceGenerator { if (item instanceof UnresolvedAVM2Item) { String fullClass = localData.getFullClass(); - item = ((UnresolvedAVM2Item) item).resolve(localData.currentClass, new TypeItem(fullClass), new ArrayList<>(), new ArrayList<>(), abcIndex, new ArrayList<>(), new ArrayList<>()); + item = ((UnresolvedAVM2Item) item).resolve(localData, localData.currentClass, new TypeItem(fullClass), new ArrayList<>(), new ArrayList<>(), abcIndex, new ArrayList<>(), new ArrayList<>()); } if (item instanceof TypeItem) { typeItem = item; @@ -2725,7 +2732,7 @@ public class AVM2SourceGenerator implements SourceGenerator { } if (typeItem instanceof UnresolvedAVM2Item) { String fullClass = localData.getFullClass(); - typeItem = ((UnresolvedAVM2Item) typeItem).resolve(localData.currentClass, new TypeItem(fullClass), new ArrayList<>(), new ArrayList<>(), abcIndex, new ArrayList<>(), new ArrayList<>()); + typeItem = ((UnresolvedAVM2Item) typeItem).resolve(localData, localData.currentClass, new TypeItem(fullClass), new ArrayList<>(), new ArrayList<>(), abcIndex, new ArrayList<>(), new ArrayList<>()); } if (!(typeItem instanceof TypeItem)) { 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 5acf22ea4..61d39c82c 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 @@ -58,6 +58,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.clauses.TryAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.AddAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.AsTypeAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.BitAndAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.operations.BitNotAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.BitOrAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.BitXorAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.DeletePropertyAVM2Item; @@ -155,7 +156,7 @@ public class ActionScript3Parser { return uniqLast; } - private List commands(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, List variables) throws IOException, AVM2ParseException { + private List commands(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, List variables) throws IOException, AVM2ParseException, InterruptedException { List ret = new ArrayList<>(); if (debugMode) { System.out.println("commands:"); @@ -170,7 +171,7 @@ public class ActionScript3Parser { return ret; } - private GraphTargetItem type(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem type(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, List variables) throws IOException, AVM2ParseException, InterruptedException { ParsedSymbol s = lex(); if (s.type == SymbolType.MULTIPLY) { return new UnboundedTypeItem(); @@ -185,7 +186,7 @@ public class ActionScript3Parser { return t; } - private GraphTargetItem memberOrCall(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem newcmds, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem memberOrCall(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem newcmds, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException, InterruptedException { if (debugMode) { System.out.println("memberOrCall:"); } @@ -239,7 +240,7 @@ public class ActionScript3Parser { return ret; } - private GraphTargetItem applyType(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem obj, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem applyType(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem obj, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException, InterruptedException { GraphTargetItem ret = obj; ParsedSymbol s = lex(); if (s.type == SymbolType.TYPENAME) { @@ -271,7 +272,7 @@ public class ActionScript3Parser { return ret; } - private GraphTargetItem member(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem obj, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem member(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem obj, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException, InterruptedException { if (debugMode) { System.out.println("member:"); } @@ -338,7 +339,7 @@ public class ActionScript3Parser { return ret; } - private GraphTargetItem name(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, boolean typeOnly, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables, List importedClasses) throws IOException, AVM2ParseException { + private GraphTargetItem name(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, boolean typeOnly, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables, List importedClasses) throws IOException, AVM2ParseException, InterruptedException { ParsedSymbol s = lex(); DottedChain name = new DottedChain(new String[]{}, ""); String name2 = ""; @@ -446,13 +447,16 @@ public class ActionScript3Parser { } } - private ParsedSymbol expectedType(Object... type) throws IOException, AVM2ParseException { + private ParsedSymbol expectedType(Object... type) throws IOException, AVM2ParseException, InterruptedException { ParsedSymbol symb = lex(); expected(symb, lexer.yyline(), type); return symb; } - private ParsedSymbol lex() throws IOException, AVM2ParseException { + private ParsedSymbol lex() throws IOException, AVM2ParseException, InterruptedException { + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException(); + } ParsedSymbol ret = lexer.lex(); if (debugMode) { System.out.println(ret); @@ -460,7 +464,7 @@ public class ActionScript3Parser { return ret; } - private List call(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private List call(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException, InterruptedException { List ret = new ArrayList<>(); //expected(SymbolType.PARENT_OPEN); //MUST BE HANDLED BY CALLER ParsedSymbol s = lex(); @@ -475,12 +479,12 @@ public class ActionScript3Parser { return ret; } - private MethodAVM2Item method(List> allOpenedNamespaces, boolean outsidePackage, boolean isPrivate, List>> metadata, NamespaceItem pkg, boolean isInterface, String customAccess, Reference needsActivation, List importedClasses, boolean override, boolean isFinal, TypeItem thisType, List openedNamespaces, boolean isStatic, String functionName, boolean isMethod, List variables) throws IOException, AVM2ParseException { + private MethodAVM2Item method(List> allOpenedNamespaces, boolean outsidePackage, boolean isPrivate, List>> metadata, NamespaceItem pkg, boolean isInterface, String customAccess, Reference needsActivation, List importedClasses, boolean override, boolean isFinal, TypeItem thisType, List openedNamespaces, boolean isStatic, String functionName, boolean isMethod, List variables) throws IOException, AVM2ParseException, InterruptedException { FunctionAVM2Item f = function(allOpenedNamespaces, metadata, pkg, isInterface, needsActivation, importedClasses, thisType, openedNamespaces, functionName, isMethod, variables); return new MethodAVM2Item(allOpenedNamespaces, outsidePackage, isPrivate, f.metadata, f.pkg, f.isInterface, customAccess, f.needsActivation, f.hasRest, f.line, override, isFinal, isStatic, functionName, f.paramTypes, f.paramNames, f.paramValues, f.body, f.subvariables, f.retType); } - private FunctionAVM2Item function(List> allOpenedNamespaces, List>> metadata, NamespaceItem pkg, boolean isInterface, Reference needsActivation, List importedClasses, TypeItem thisType, List openedNamespaces, String functionName, boolean isMethod, List variables) throws IOException, AVM2ParseException { + private FunctionAVM2Item function(List> allOpenedNamespaces, List>> metadata, NamespaceItem pkg, boolean isInterface, Reference needsActivation, List importedClasses, TypeItem thisType, List openedNamespaces, String functionName, boolean isMethod, List variables) throws IOException, AVM2ParseException, InterruptedException { openedNamespaces = new ArrayList<>(openedNamespaces); //local copy allOpenedNamespaces.add(openedNamespaces); @@ -561,7 +565,7 @@ public class ActionScript3Parser { return new FunctionAVM2Item(metadata, pkg, isInterface, needsActivation2.getVal(), hasRest, line, functionName, paramTypes, paramNames, paramValues, body, subvariables, retType); } - private List>> parseMetadata() throws IOException, AVM2ParseException { + private List>> parseMetadata() throws IOException, AVM2ParseException, InterruptedException { List>> metadata = new ArrayList<>(); ParsedSymbol s = lex(); while (s.isType(SymbolType.BRACKET_OPEN)) { @@ -600,12 +604,12 @@ public class ActionScript3Parser { return metadata; } - private void classTraits(List> allOpenedNamespaces, boolean outsidePackage, List cinitVariables, Reference cinitNeedsActivation, List cinit, List importedClasses, List openedNamespaces, NamespaceItem pkg, String classNameStr, boolean isInterface, List traits, List iinitVariables, Reference iinitNeedsActivation, Reference iinit) throws AVM2ParseException, IOException, CompilationException { + private void classTraits(List> allOpenedNamespaces, boolean outsidePackage, List cinitVariables, Reference cinitNeedsActivation, List cinit, List importedClasses, List openedNamespaces, NamespaceItem pkg, String classNameStr, boolean isInterface, List traits, List iinitVariables, Reference iinitNeedsActivation, Reference iinit) throws AVM2ParseException, IOException, CompilationException, InterruptedException { NamespaceItem publicNs = new NamespaceItem("", Namespace.KIND_PACKAGE); - NamespaceItem privateNs = new NamespaceItem(pkg.name.toRawString() + ":" + classNameStr, Namespace.KIND_PRIVATE); - NamespaceItem protectedNs = new NamespaceItem(pkg.name.toRawString() + ":" + classNameStr, Namespace.KIND_PROTECTED); - NamespaceItem staticProtectedNs = new NamespaceItem(pkg.name.toRawString() + ":" + classNameStr, Namespace.KIND_STATIC_PROTECTED); + NamespaceItem privateNs = new NamespaceItem(pkg.name.toRawString().isEmpty() ? classNameStr : pkg.name.toRawString() + ":" + classNameStr, Namespace.KIND_PRIVATE); + NamespaceItem protectedNs = new NamespaceItem(pkg.name.toRawString().isEmpty() ? classNameStr : pkg.name.toRawString() + ":" + classNameStr, Namespace.KIND_PROTECTED); + NamespaceItem staticProtectedNs = new NamespaceItem(pkg.name.toRawString().isEmpty() ? classNameStr : pkg.name.toRawString() + ":" + classNameStr, Namespace.KIND_STATIC_PROTECTED); NamespaceItem packageInternalNs = new NamespaceItem(pkg.name, Namespace.KIND_PACKAGE_INTERNAL); openedNamespaces = new ArrayList<>(openedNamespaces); @@ -868,14 +872,14 @@ public class ActionScript3Parser { } } - private void scriptTraits(List> allOpenedNamespaces, int scriptIndex, String scriptName, List traits) throws AVM2ParseException, IOException, CompilationException { + private void scriptTraits(List> allOpenedNamespaces, int scriptIndex, String scriptName, List traits) throws AVM2ParseException, IOException, CompilationException, InterruptedException { while (scriptTraitsBlock(allOpenedNamespaces, scriptIndex, scriptName, traits)) { //empty } } - private boolean scriptTraitsBlock(List> allOpenedNamespaces, int scriptIndex, String scriptName, List traits) throws AVM2ParseException, IOException, CompilationException { + private boolean scriptTraitsBlock(List> allOpenedNamespaces, int scriptIndex, String scriptName, List traits) throws AVM2ParseException, IOException, CompilationException, InterruptedException { ParsedSymbol s; boolean inPackage = false; s = lex(); @@ -1010,7 +1014,8 @@ public class ActionScript3Parser { List names = new ArrayList<>(); List namespaces = new ArrayList<>(); //FIXME for Private classes in script (?) - AVM2SourceGenerator.parentNamesAddNames(abcIndex, AVM2SourceGenerator.resolveType(new SourceGeneratorLocalData(new HashMap<>(), 0, false, 0), ((TypeItem) ((UnresolvedAVM2Item) extendsTypeStr).resolve(pkgName.addWithSuffix(subNameStr).toRawString(), null, new ArrayList<>(), new ArrayList<>(), abcIndex, new ArrayList<>(), new ArrayList<>())), abcIndex), indices, names, namespaces); + AVM2SourceGenerator.parentNamesAddNames(abcIndex, AVM2SourceGenerator.resolveType(new SourceGeneratorLocalData(new HashMap<>(), 0, false, 0), ((TypeItem) ((UnresolvedAVM2Item) extendsTypeStr) + .resolve(null, pkgName.addWithSuffix(subNameStr).toRawString(), null, new ArrayList<>(), new ArrayList<>(), abcIndex, new ArrayList<>(), new ArrayList<>())), abcIndex), indices, names, namespaces); for (int i = 0; i < names.size(); i++) { if (namespaces.get(i) == null || namespaces.get(i).isEmpty()) { continue; @@ -1218,7 +1223,7 @@ public class ActionScript3Parser { } } - private List xmltag(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference usesVars, List openedTags, Reference closedVarTags, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private List xmltag(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference usesVars, List openedTags, Reference closedVarTags, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException, InterruptedException { ParsedSymbol s; List rets = new ArrayList<>(); //GraphTargetItem ret = null; @@ -1347,7 +1352,7 @@ public class ActionScript3Parser { return rets; } - private GraphTargetItem xml(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem xml(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException, InterruptedException { List openedTags = new ArrayList<>(); int closedVarTags = 0; @@ -1358,7 +1363,7 @@ public class ActionScript3Parser { return ret; } - private GraphTargetItem command(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, boolean mustBeCommand, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem command(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, boolean mustBeCommand, List variables) throws IOException, AVM2ParseException, InterruptedException { LexBufferer buf = new LexBufferer(); lexer.addListener(buf); GraphTargetItem ret = null; @@ -1749,7 +1754,7 @@ public class ActionScript3Parser { UnresolvedAVM2Item ui = (UnresolvedAVM2Item) a; if (ui.getVariableName().equals(DottedChain.parseWithSuffix(e.getVariableName()))) { try { - ui.resolve(null, null, new ArrayList<>(), new ArrayList<>(), abcIndex, new ArrayList<>(), variables); + ui.resolve(null, null, null, new ArrayList<>(), new ArrayList<>(), abcIndex, new ArrayList<>(), variables); } catch (CompilationException ex) { // ignore } @@ -1772,7 +1777,7 @@ public class ActionScript3Parser { for (NameAVM2Item e : catchExceptions) { if (ui.getVariableName().equals(DottedChain.parseWithSuffix(e.getVariableName()))) { try { - ui.resolve(null, null, new ArrayList<>(), new ArrayList<>(), abcIndex, new ArrayList<>(), variables); + ui.resolve(null, null, null, new ArrayList<>(), new ArrayList<>(), abcIndex, new ArrayList<>(), variables); } catch (CompilationException ex) { // ignore } @@ -1835,7 +1840,7 @@ public class ActionScript3Parser { } - private GraphTargetItem expression(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables, boolean allowComma) throws IOException, AVM2ParseException { + private GraphTargetItem expression(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables, boolean allowComma) throws IOException, AVM2ParseException, InterruptedException { return expression(allOpenedNamespaces, thisType, pkg, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, allowRemainder, variables, allowComma); } @@ -1869,7 +1874,7 @@ public class ActionScript3Parser { return (item instanceof NameAVM2Item); } - private int brackets(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, List ret, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private int brackets(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, List ret, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException, InterruptedException { ParsedSymbol s = lex(); int arrCnt = 0; if (s.type == SymbolType.BRACKET_OPEN) { @@ -1893,7 +1898,7 @@ public class ActionScript3Parser { return arrCnt; } - private GraphTargetItem expression(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables, boolean allowComma) throws IOException, AVM2ParseException { + private GraphTargetItem expression(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables, boolean allowComma) throws IOException, AVM2ParseException, InterruptedException { List commaItems = new ArrayList<>(); ParsedSymbol symb; @@ -1953,7 +1958,7 @@ public class ActionScript3Parser { } } - private ParsedSymbol peekExprToken() throws IOException, AVM2ParseException { + private ParsedSymbol peekExprToken() throws IOException, AVM2ParseException, InterruptedException { ParsedSymbol lookahead = lex(); xmlToLowerThanFix(lookahead); regexpToDivideFix(lookahead); @@ -1962,7 +1967,7 @@ public class ActionScript3Parser { return lookahead; } - private GraphTargetItem expression1(List> allOpenedNamespaces, GraphTargetItem lhs, int min_precedence, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem expression1(List> allOpenedNamespaces, GraphTargetItem lhs, int min_precedence, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException, InterruptedException { if (debugMode) { System.out.println("expression1:"); } @@ -2175,7 +2180,7 @@ public class ActionScript3Parser { return lhs; } - private GraphTargetItem expressionPrimary(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem expressionPrimary(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException, InterruptedException { if (debugMode) { System.out.println("primary:"); } @@ -2252,7 +2257,7 @@ public class ActionScript3Parser { break; case NEGATE: ret = expressionPrimary(allOpenedNamespaces, thisType, pkg, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, false, variables); - ret = new NegAVM2Item(null, null, ret); + ret = new BitNotAVM2Item(null, null, ret); break; case MINUS: @@ -2470,7 +2475,7 @@ public class ActionScript3Parser { private List constantPool; - private List parseImportsUsages(List openedNamespaces) throws IOException, AVM2ParseException { + private List parseImportsUsages(List openedNamespaces) throws IOException, AVM2ParseException, InterruptedException { ParsedSymbol s; List importedClasses = new ArrayList<>(); @@ -2517,7 +2522,7 @@ public class ActionScript3Parser { return importedClasses; } - private List parseScript(List> allOpenedNamespaces, int scriptIndex, String fileName) throws IOException, AVM2ParseException, CompilationException { + private List parseScript(List> allOpenedNamespaces, int scriptIndex, String fileName) throws IOException, AVM2ParseException, CompilationException, InterruptedException { //int scriptPrivateNs; if (fileName.contains("/")) { @@ -2531,7 +2536,7 @@ public class ActionScript3Parser { return items; } - public List scriptTraitsFromString(List> allOpenedNamespaces, String str, String fileName, int scriptIndex) throws AVM2ParseException, IOException, CompilationException { + public List scriptTraitsFromString(List> allOpenedNamespaces, String str, String fileName, int scriptIndex) throws AVM2ParseException, IOException, CompilationException, InterruptedException { lexer = new ActionScriptLexer(str); List ret = parseScript(allOpenedNamespaces, scriptIndex, fileName); @@ -2548,7 +2553,7 @@ public class ActionScript3Parser { abcIndex.getSelectedAbc().script_info.add(gen.generateScriptInfo(allOpenedNamespaces, localData, items, classPos)); } - public void addScript(String s, String fileName, int classPos, int scriptIndex) throws AVM2ParseException, IOException, CompilationException { + public void addScript(String s, String fileName, int classPos, int scriptIndex) throws AVM2ParseException, IOException, CompilationException, InterruptedException { List> allOpenedNamespaces = new ArrayList<>(); List traits = scriptTraitsFromString(allOpenedNamespaces, s, fileName, scriptIndex); addScriptFromTree(allOpenedNamespaces, traits, classPos); 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 dac380048..1e29309cb 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 @@ -78,34 +78,34 @@ public class CallAVM2Item extends AVM2Item { } if (callable instanceof NameAVM2Item) { NameAVM2Item n = (NameAVM2Item) callable; - /*List allAbcs = new ArrayList<>(); - allAbcs.add(g.abc); - allAbcs.addAll(g.allABCs);*/ - String cname = localData.currentClass; - DottedChain pkgName = localData.pkg; - GraphTargetItem obj = null; - Reference outName = new Reference<>(""); - Reference outNs = new Reference<>(DottedChain.EMPTY); - Reference outPropNs = new Reference<>(DottedChain.EMPTY); - Reference outPropNsKind = new Reference<>(1); - Reference outPropNsIndex = new Reference<>(0); - Reference outPropType = new Reference<>(null); - Reference outPropValue = new Reference<>(null); - Reference outPropValueABC = new Reference<>(null); - List otherNs = new ArrayList<>(); - for (NamespaceItem on : openedNamespaces) { - if (on.isResolved()) { - otherNs.add(on.getCpoolIndex(g.abcIndex)); + if (!localData.registerVars.containsKey(n.getVariableName())) { + String cname = localData.currentClass; + DottedChain pkgName = localData.pkg; + GraphTargetItem obj = null; + Reference outName = new Reference<>(""); + Reference outNs = new Reference<>(DottedChain.EMPTY); + Reference outPropNs = new Reference<>(DottedChain.EMPTY); + Reference outPropNsKind = new Reference<>(1); + Reference outPropNsIndex = new Reference<>(0); + Reference outPropType = new Reference<>(null); + Reference outPropValue = new Reference<>(null); + Reference outPropValueABC = new Reference<>(null); + List otherNs = new ArrayList<>(); + Reference isType = new Reference<>(false); + for (NamespaceItem on : openedNamespaces) { + if (on.isResolved()) { + otherNs.add(on.getCpoolIndex(g.abcIndex)); + } } + if (cname != null && AVM2SourceGenerator.searchPrototypeChain(otherNs, localData.privateNs, localData.protectedNs, true, g.abcIndex, pkgName, cname, n.getVariableName(), outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueABC, isType)) { + NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), n.line, "this", null, false, n.openedNamespaces, abcIndex); + nobj.setRegNumber(0); + obj = nobj; + } + PropertyAVM2Item p = new PropertyAVM2Item(obj, n.getVariableName(), g.abcIndex, n.openedNamespaces, new ArrayList<>()); + p.setAssignedValue(n.getAssignedValue()); + callable = p; } - if (cname != null && AVM2SourceGenerator.searchPrototypeChain(otherNs, 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, abcIndex); - nobj.setRegNumber(0); - obj = nobj; - } - PropertyAVM2Item p = new PropertyAVM2Item(obj, n.getVariableName(), g.abcIndex, n.openedNamespaces, new ArrayList<>()); - p.setAssignedValue(n.getAssignedValue()); - callable = p; } int propIndex = -1; @@ -133,6 +133,7 @@ public class CallAVM2Item extends AVM2Item { Reference outPropType = new Reference<>(null); Reference outPropValue = new Reference<>(null); Reference outPropValueAbc = new Reference<>(null); + Reference isType = new Reference<>(false); List otherNs = new ArrayList<>(); for (NamespaceItem n : openedNamespaces) { @@ -141,7 +142,7 @@ public class CallAVM2Item extends AVM2Item { } } - if (cname != null && AVM2SourceGenerator.searchPrototypeChain(otherNs, localData.privateNs, localData.protectedNs, true, g.abcIndex, pkgName, cname, prop.propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc) && (localData.getFullClass().equals(outNs.getVal().addWithSuffix(outName.getVal()).toRawString()))) { + if (cname != null && AVM2SourceGenerator.searchPrototypeChain(otherNs, localData.privateNs, localData.protectedNs, true, g.abcIndex, pkgName, cname, prop.propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc, isType) && (localData.getFullClass().equals(outNs.getVal().addWithSuffix(outName.getVal()).toRawString()))) { NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), 0, "this", null, false, new ArrayList<>(), abcIndex); nobj.setRegNumber(0); obj = nobj; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/IndexAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/IndexAVM2Item.java index 5a01cd2fe..e6db3a758 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/IndexAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/IndexAVM2Item.java @@ -154,13 +154,16 @@ public class IndexAVM2Item extends AssignableAVM2Item { } else { return toSourceMerge(localData, generator, object, - call ? ins(AVM2Instructions.Dup) : null, + call ? dupSetTemp(localData, generator, ret_temp) : null, index, + construct ? getTemp(localData, generator, ret_temp) : null, construct ? callargs : null, ins(construct ? AVM2Instructions.ConstructProp : delete ? AVM2Instructions.DeleteProperty : AVM2Instructions.GetProperty, indexPropIndex, construct ? callargs.size() : null), + call ? getTemp(localData, generator, ret_temp) : null, call ? callargs : null, call ? ins(AVM2Instructions.Call, callargs.size()) : null, - needsReturn ? null : ins(AVM2Instructions.Pop)); + needsReturn ? null : ins(AVM2Instructions.Pop), + (call || construct) ? killTemp(localData, generator, Arrays.asList(ret_temp)) : null); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespaceItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespaceItem.java index f546b9c09..4a2c93a97 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespaceItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespaceItem.java @@ -89,8 +89,9 @@ public class NamespaceItem { PropertyAVM2Item prop = new PropertyAVM2Item(null, custom, abcIndex, openedNamespaces, new ArrayList<>()); Reference value = new Reference<>(null); Reference outAbc = new Reference<>(null); + Reference isType = new Reference<>(false); - prop.resolve(true, localData, new Reference<>(null), new Reference<>(null), new Reference<>(0), value, outAbc); + prop.resolve(true, localData, isType, new Reference<>(null), new Reference<>(null), new Reference<>(0), value, outAbc); boolean resolved = true; if (value.getVal() == null) { resolved = false; 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 2655afc99..02b231b57 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 @@ -31,6 +31,7 @@ import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.abc.types.ScriptInfo; import com.jpexs.decompiler.flash.abc.types.ValueKind; import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; @@ -132,7 +133,8 @@ public class PropertyAVM2Item extends AssignableAVM2Item { return multinameToType(new HashSet<>(), m_index, constants); } - public void resolve(boolean mustExist, SourceGeneratorLocalData localData, Reference objectType, Reference propertyType, Reference propertyIndex, Reference propertyValue, Reference propertyValueABC) throws CompilationException { + public void resolve(boolean mustExist, SourceGeneratorLocalData localData, Reference isType, Reference objectType, Reference propertyType, Reference propertyIndex, Reference propertyValue, Reference propertyValueABC) throws CompilationException { + isType.setVal(false); GraphTargetItem thisType = new TypeItem(localData.getFullClass()); GraphTargetItem objType = null; GraphTargetItem objSubType = null; @@ -269,7 +271,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { propValueAbc = sp.abc; } } - if (propType == null && AVM2SourceGenerator.searchPrototypeChain(otherNs, localData.privateNs, localData.protectedNs, false, abcIndex, ftn.getWithoutLast(), ftn.getLast(), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc)) { + if (propType == null && AVM2SourceGenerator.searchPrototypeChain(otherNs, localData.privateNs, localData.protectedNs, false, abcIndex, ftn.getWithoutLast(), ftn.getLast(), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc, isType)) { objType = new TypeItem(outNs.getVal().addWithSuffix(outName.getVal())); propType = outPropType.getVal(); propIndex = constants.getMultinameId(Multiname.createQName(false, @@ -356,6 +358,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { } for (Trait t : si.traits.traits) { if (t.name_index == name_index) { + isType.setVal(t instanceof TraitClass); objType = new TypeItem(DottedChain.OBJECT); propType = AVM2SourceGenerator.getTraitReturnType(abcIndex, t); propIndex = t.name_index; @@ -387,7 +390,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { otherns.add(n.getCpoolIndex(abcIndex)); } } - if (AVM2SourceGenerator.searchPrototypeChain(otherns, localData.privateNs, localData.protectedNs, false, abcIndex, nsname, (((TypeItem) p.objType).fullTypeName.getLast()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc)) { + if (AVM2SourceGenerator.searchPrototypeChain(otherns, localData.privateNs, localData.protectedNs, false, abcIndex, nsname, (((TypeItem) p.objType).fullTypeName.getLast()), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc, isType)) { objType = new TypeItem(outNs.getVal().addWithSuffix(outName.getVal())); propType = p.returnType; propIndex = constants.getMultinameId(Multiname.createQName(false, @@ -446,7 +449,8 @@ public class PropertyAVM2Item extends AssignableAVM2Item { Reference propIndex = new Reference<>(0); Reference outPropValue = new Reference<>(null); Reference outPropValueAbc = new Reference<>(null); - resolve(false, localData, objType, propType, propIndex, outPropValue, outPropValueAbc); + Reference isType = new Reference<>(false); + resolve(false, localData, isType, objType, propType, propIndex, outPropValue, outPropValueAbc); return propIndex.getVal(); } @@ -458,8 +462,9 @@ public class PropertyAVM2Item extends AssignableAVM2Item { Reference propIndex = new Reference<>(0); Reference outPropValue = new Reference<>(null); Reference outPropValueAbc = new Reference<>(null); + Reference isType = new Reference<>(false); try { - resolve(false, new SourceGeneratorLocalData(new HashMap<>(), 0, false, 0)/*???*/, objType, propType, propIndex, outPropValue, outPropValueAbc); + resolve(false, new SourceGeneratorLocalData(new HashMap<>(), 0, false, 0)/*???*/, isType, objType, propType, propIndex, outPropValue, outPropValueAbc); return propType.getVal(); } catch (CompilationException ex) { @@ -475,8 +480,9 @@ public class PropertyAVM2Item extends AssignableAVM2Item { Reference propIndex = new Reference<>(0); Reference outPropValue = new Reference<>(null); Reference outPropValueAbc = new Reference<>(null); + Reference isType = new Reference<>(false); - resolve(false, localData, objType, propType, propIndex, outPropValue, outPropValueAbc); + resolve(false, localData, isType, objType, propType, propIndex, outPropValue, outPropValueAbc); int propertyId = propIndex.getVal(); Object obj = resolveObject(localData, generator); @@ -539,6 +545,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { Reference outPropType = new Reference<>(null); Reference outPropValue = new Reference<>(null); Reference outPropValueAbc = new Reference<>(null); + Reference isType = new Reference<>(false); /*List abcs = new ArrayList<>(); abcs.add(abc); @@ -549,7 +556,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { otherNs.add(n.getCpoolIndex(abcIndex)); } } - if (!localData.subMethod && cname != null && AVM2SourceGenerator.searchPrototypeChain(otherNs, localData.privateNs, localData.protectedNs, true, abcIndex, pkgName, cname, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc) && (localData.getFullClass().equals(outNs.getVal().addWithSuffix(outName.getVal()).toRawString()))) { + if (!localData.subMethod && cname != null && AVM2SourceGenerator.searchPrototypeChain(otherNs, localData.privateNs, localData.protectedNs, true, abcIndex, pkgName, cname, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc, isType) && (localData.getFullClass().equals(outNs.getVal().addWithSuffix(outName.getVal()).toRawString()))) { NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), 0, "this", null, false, openedNamespaces, abcIndex); nobj.setRegNumber(0); obj = nobj; @@ -560,7 +567,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { Reference propValue = new Reference<>(null); Reference propValueAbc = new Reference<>(null); - resolve(false, localData, objType, propType, propIndex, outPropValue, propValueAbc); + resolve(false, localData, isType, objType, propType, propIndex, outPropValue, propValueAbc); obj = ins(AVM2Instructions.FindPropertyStrict, propIndex.getVal()); } } @@ -575,8 +582,9 @@ public class PropertyAVM2Item extends AssignableAVM2Item { Reference propIndex = new Reference<>(0); Reference outPropValue = new Reference<>(null); Reference outPropValueAbc = new Reference<>(null); + Reference isType = new Reference<>(false); - resolve(false, localData, objType, propType, propIndex, outPropValue, outPropValueAbc); + resolve(false, localData, isType, objType, propType, propIndex, outPropValue, outPropValueAbc); int propertyId = propIndex.getVal(); Object obj = resolveObject(localData, generator); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java index d6037fb7a..fd2e223d0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java @@ -17,6 +17,7 @@ package com.jpexs.decompiler.flash.abc.avm2.parser.script; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions; import com.jpexs.decompiler.flash.abc.avm2.model.BooleanAVM2Item; @@ -27,6 +28,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.Namespace; +import com.jpexs.decompiler.flash.abc.types.ValueKind; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; @@ -36,6 +38,7 @@ 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 com.jpexs.helpers.Reference; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -284,7 +287,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { throw new RuntimeException("Cannot assign"); } - public GraphTargetItem resolve(String currentClass, GraphTargetItem thisType, List paramTypes, List paramNames, AbcIndexing abc, List callStack, List variables) throws CompilationException { + public GraphTargetItem resolve(SourceGeneratorLocalData localData /*can be null!!!*/, String currentClass, GraphTargetItem thisType, List paramTypes, List paramNames, AbcIndexing abc, List callStack, List variables) throws CompilationException { if (scopeStack.isEmpty()) { //Everything is multiname property in with command //search for variable @@ -313,7 +316,49 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { } } - if (currentClass != null) { + if ((paramNames.contains(name.get(0)) || name.get(0).equals("arguments"))) { + int ind = paramNames.indexOf(name.get(0)); + GraphTargetItem t = TypeItem.UNBOUNDED; + if (ind == -1) { + + } else if (ind < paramTypes.size()) { + t = paramTypes.get(ind); + } //else rest parameter + + GraphTargetItem ret = new NameAVM2Item(t, line, name.get(0), null, false, openedNamespaces, abcIndex); + resolved = ret; + for (int i = 1; i < name.size(); i++) { + resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>()); + if (i == name.size() - 1) { + ((PropertyAVM2Item) resolved).assignedValue = assignedValue; + } + } + if (name.size() == 1) { + ((NameAVM2Item) ret).setAssignedValue(assignedValue); + } + return resolvedRoot = ret; + } + + boolean isProperty = false; + if (localData != null) { //resolve can be called without localData + PropertyAVM2Item resolvedx = new PropertyAVM2Item(null, name.get(0), abc, openedNamespaces, callStack); + ((PropertyAVM2Item) resolvedx).scopeStack = scopeStack; + ((PropertyAVM2Item) resolvedx).setAssignedValue(assignedValue); + Reference objectType = new Reference<>(null); + Reference propertyType = new Reference<>(null); + Reference propertyIndex = new Reference<>(null); + Reference propertyValue = new Reference<>(null); + Reference propertyValueABC = new Reference<>(null); + Reference isType = new Reference<>(false); + + resolvedx.resolve(true, localData, isType, objectType, propertyType, propertyIndex, propertyValue, propertyValueABC); + + if (objectType.getVal() != null && !isType.getVal()) { + isProperty = true; + } + } + + if (currentClass != null && !isProperty) { DottedChain classChain = DottedChain.parseWithSuffix(currentClass); DottedChain pkg = classChain.getWithoutLast(); @@ -334,87 +379,87 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { } //Search for types in imported classes - for (DottedChain imp : importedClasses) { - String impName = imp.getLast(); + if (!isProperty) { + for (DottedChain imp : importedClasses) { + String impName = imp.getLast(); - if (impName.equals(name.get(0))) { - TypeItem ret = new TypeItem(imp); - resolved = ret; - for (int i = 1; i < name.size(); i++) { - resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>()); - if (i == name.size() - 1) { - ((PropertyAVM2Item) resolved).assignedValue = assignedValue; - } - } - - if (name.size() == 1) { - AbcIndexing.TraitIndex ti = abc.findScriptProperty(imp); - if (ti != null && (ti.trait instanceof TraitSlotConst)) { - resolved = new ImportedSlotConstItem(ret); - if (assignedValue != null) { - ((ImportedSlotConstItem) resolved).assignedValue = assignedValue; + if (impName.equals(name.get(0))) { + TypeItem ret = new TypeItem(imp); + resolved = ret; + for (int i = 1; i < name.size(); i++) { + resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>()); + if (i == name.size() - 1) { + ((PropertyAVM2Item) resolved).assignedValue = assignedValue; } } - } - return resolvedRoot = ret; + if (name.size() == 1) { + AbcIndexing.TraitIndex ti = abc.findScriptProperty(imp); + if (ti != null && (ti.trait instanceof TraitSlotConst)) { + resolved = new ImportedSlotConstItem(ret); + if (assignedValue != null) { + ((ImportedSlotConstItem) resolved).assignedValue = assignedValue; + } + } + } + + return resolvedRoot = ret; + } } } //Search all fully qualitfied types - /*List allAbcs = new ArrayList<>(); - allAbcs.add(abc); - allAbcs.addAll(otherAbcs);*/ - for (int i = 0; i < name.size(); i++) { - DottedChain fname = name.subChain(i + 1); - AbcIndexing.ClassIndex ci = abc.findClass(new TypeItem(fname)); - if (ci != null) { - if (!subtypes.isEmpty() && name.size() > i + 1) { - continue; - } - TypeItem ret = new TypeItem(fname); - resolved = ret; - for (int j = i + 1; j < name.size(); j++) { - resolved = new PropertyAVM2Item(resolved, name.get(j), abc, openedNamespaces, new ArrayList<>()); - if (j == name.size() - 1) { - ((PropertyAVM2Item) resolved).assignedValue = assignedValue; + if (!isProperty) { + for (int i = 0; i < name.size(); i++) { + DottedChain fname = name.subChain(i + 1); + AbcIndexing.ClassIndex ci = abc.findClass(new TypeItem(fname)); + if (ci != null) { + if (!subtypes.isEmpty() && name.size() > i + 1) { + continue; + } + TypeItem ret = new TypeItem(fname); + resolved = ret; + for (int j = i + 1; j < name.size(); j++) { + resolved = new PropertyAVM2Item(resolved, name.get(j), abc, openedNamespaces, new ArrayList<>()); + if (j == name.size() - 1) { + ((PropertyAVM2Item) resolved).assignedValue = assignedValue; + } + } + if (name.size() == i + 1 && assignedValue != null) { + throw new CompilationException("Cannot assign type", line); } - } - if (name.size() == i + 1 && assignedValue != null) { - throw new CompilationException("Cannot assign type", line); - } - return resolvedRoot = ret; + return resolvedRoot = ret; + } + } + + //Search for types in opened namespaces + for (NamespaceItem n : openedNamespaces) { + Namespace ons = abc.getSelectedAbc().constants.getNamespace(n.getCpoolIndex(abc)); + TypeItem ti = new TypeItem(ons.getName(abc.getSelectedAbc().constants).addWithSuffix(name.get(0))); + AbcIndexing.ClassIndex ci = abc.findClass(ti); + if (ci != null) { + if (!subtypes.isEmpty() && name.size() > 1) { + continue; + } + TypeItem ret = ti; + resolved = ret; + for (int i = 1; i < name.size(); i++) { + resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>()); + if (i == name.size() - 1) { + ((PropertyAVM2Item) resolved).assignedValue = assignedValue; + } + } + if (name.size() == 1 && assignedValue != null) { + throw new CompilationException("Cannot assign type", line); + } + + return resolvedRoot = ret; + } } } - //Search for types in opened namespaces - for (NamespaceItem n : openedNamespaces) { - Namespace ons = abc.getSelectedAbc().constants.getNamespace(n.getCpoolIndex(abc)); - TypeItem ti = new TypeItem(ons.getName(abc.getSelectedAbc().constants).addWithSuffix(name.get(0))); - AbcIndexing.ClassIndex ci = abc.findClass(ti); - if (ci != null) { - if (!subtypes.isEmpty() && name.size() > 1) { - continue; - } - TypeItem ret = ti; - resolved = ret; - for (int i = 1; i < name.size(); i++) { - resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>()); - if (i == name.size() - 1) { - ((PropertyAVM2Item) resolved).assignedValue = assignedValue; - } - } - if (name.size() == 1 && assignedValue != null) { - throw new CompilationException("Cannot assign type", line); - } - - return resolvedRoot = ret; - } - } - - if (name.get( - 0).equals("this") || name.get(0).equals("super")) { + if (!isProperty && (name.get(0).equals("this") || name.get(0).equals("super"))) { if (thisType == null) { throw new CompilationException("Cannot use this in that context", line); } @@ -448,41 +493,9 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { return resolvedRoot = ret; } - if (paramNames.contains(name.get(0)) || name.get(0).equals("arguments")) { - int ind = paramNames.indexOf(name.get(0)); - GraphTargetItem t = TypeItem.UNBOUNDED; - if (ind == -1) { - } else if (ind < paramTypes.size()) { - t = paramTypes.get(ind); - } //else rest parameter - - GraphTargetItem ret = new NameAVM2Item(t, line, name.get(0), null, false, openedNamespaces, abcIndex); - resolved = ret; - for (int i = 1; i < name.size(); i++) { - resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>()); - if (i == name.size() - 1) { - ((PropertyAVM2Item) resolved).assignedValue = assignedValue; - } - } - if (name.size() == 1) { - ((NameAVM2Item) ret).setAssignedValue(assignedValue); - } - return resolvedRoot = ret; - } - - if (/*!subtypes.isEmpty() && */name.size() - == 1 && name.get(0).equals("Vector")) { + if (!isProperty && (name.size() == 1 && name.get(0).equals("Vector"))) { TypeItem ret = new TypeItem(InitVectorAVM2Item.VECTOR_FQN); - /*for (String s : subtypes) { - UnresolvedAVM2Item su = new UnresolvedAVM2Item(new ArrayList<>(), importedClasses, true, null, line, s, null, openedNamespaces); - su.resolve(thisType, paramTypes, paramNames, abc, otherAbcs, callStack, variables); - if (!(su.resolved instanceof TypeItem)) { - throw new CompilationException("Not a type", line); - } - TypeItem st = (TypeItem) su.resolved; - ret.subtypes.add(st.fullTypeName); - }*/ resolved = ret; return resolvedRoot = ret; } @@ -492,9 +505,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { } resolved = null; GraphTargetItem ret = null; - for (int i = 0; - i < name.size(); - i++) { + for (int i = 0; i < name.size(); i++) { resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, callStack); if (ret == null) { ((PropertyAVM2Item) resolved).scopeStack = scopeStack; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/MethodNameMultinameUsage.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/MethodNameMultinameUsage.java index 123c1af7f..612b4af03 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/MethodNameMultinameUsage.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/MethodNameMultinameUsage.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.usages; import com.jpexs.decompiler.flash.abc.ABC; @@ -39,6 +40,14 @@ public class MethodNameMultinameUsage extends MethodMultinameUsage implements De TraitMultinameUsage otherTrait = (TraitMultinameUsage) other; if (otherTrait.classIndex == classIndex && otherTrait.traitsType == traitsType && otherTrait.parentTraitIndex == parentTraitIndex) { if (other.sameMultinameName(this)) { + + if(other instanceof MethodNameMultinameUsage){ + MethodNameMultinameUsage otherM = (MethodNameMultinameUsage)other; + //getter/setter/method must match + if(otherM.traits.traits.get(otherM.traitIndex).kindType != traits.traits.get(traitIndex).kindType){ + return false; + } + } return true; } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java index 68dbdc0c7..6519af1b0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java @@ -23,6 +23,7 @@ import static com.jpexs.decompiler.flash.action.Action.adr2ip; import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; import com.jpexs.decompiler.flash.action.model.EnumerateActionItem; import com.jpexs.decompiler.flash.action.model.FunctionActionItem; +import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; import com.jpexs.decompiler.flash.action.model.GetPropertyActionItem; import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; import com.jpexs.decompiler.flash.action.model.SetTarget2ActionItem; @@ -492,8 +493,7 @@ public class ActionGraph extends Graph { caseValuesMap.add(set.rightSide); if (set.leftSide instanceof StoreRegisterActionItem) { switchedObject = ((StoreRegisterActionItem) set.leftSide).value; - } - if (set.leftSide instanceof GetVariableActionItem) { + } else { switchedObject = set.leftSide; } @@ -600,7 +600,8 @@ public class ActionGraph extends Graph { @Override public SecondPassData prepareSecondPass(List list) { ActionSecondPassData spd = new ActionSecondPassData(); - checkSecondPassSwitches(list, spd.switchParts, spd.switchOnFalseParts, spd.switchCaseExpressions); + Set processedIfs = new HashSet<>(); + checkSecondPassSwitches(processedIfs, list, spd.switchParts, spd.switchOnFalseParts, spd.switchCaseExpressions); if (spd.switchParts.isEmpty()) { return null; //no need to second pass @@ -608,64 +609,75 @@ public class ActionGraph extends Graph { return spd; } - private void checkSecondPassSwitches(List list, List> allSwitchParts, List> allSwitchOnFalseParts, List> allSwitchExpressions) { + private void checkSecondPassSwitches(Set processedIfs, List list, List> allSwitchParts, List> allSwitchOnFalseParts, List> allSwitchExpressions) { for (GraphTargetItem item : list) { - List> walkNext = new ArrayList<>(); - boolean canUseBlock = true; if (item instanceof IfItem) { IfItem ii = (IfItem) item; boolean isNeq = true; - if ((ii.expression instanceof StrictNeqActionItem) || (ii.expression instanceof StrictEqActionItem)) { - isNeq = (ii.expression instanceof StrictNeqActionItem); + if (!processedIfs.contains(ii.decisionPart)) { + if ((ii.expression instanceof StrictNeqActionItem) || (ii.expression instanceof StrictEqActionItem)) { + isNeq = (ii.expression instanceof StrictNeqActionItem); - List switchParts = new ArrayList<>(); - List switchExpressions = new ArrayList<>(); - List switchOnFalseParts = new ArrayList<>(); - BinaryOpItem sneq = (BinaryOpItem) ii.expression; - if ((sneq.leftSide instanceof StoreRegisterActionItem) || (sneq.leftSide instanceof GetVariableActionItem)) { + List switchParts = new ArrayList<>(); + List switchExpressions = new ArrayList<>(); + List switchOnFalseParts = new ArrayList<>(); + BinaryOpItem sneq = (BinaryOpItem) ii.expression; + if (true) { + /*(sneq.leftSide instanceof StoreRegisterActionItem) + || (sneq.leftSide instanceof GetVariableActionItem) + || (sneq.leftSide instanceof GetMemberActionItem) + ) {*/ - int regId = -1; - GetVariableActionItem svar = null; - if (sneq.leftSide instanceof StoreRegisterActionItem) { - StoreRegisterActionItem sr = (StoreRegisterActionItem) sneq.leftSide; - regId = sr.register.number; - } else { - svar = (GetVariableActionItem) sneq.leftSide; - } + int regId = -1; + GraphTargetItem svar = null; + if (sneq.leftSide instanceof StoreRegisterActionItem) { + StoreRegisterActionItem sr = (StoreRegisterActionItem) sneq.leftSide; + regId = sr.register.number; + } else { + svar = sneq.leftSide; + } - switchParts.add(ii.decisionPart); - switchExpressions.add(sneq.rightSide); - switchOnFalseParts.add(ii.onTruePart); + switchParts.add(ii.decisionPart); + switchExpressions.add(sneq.rightSide); + switchOnFalseParts.add(ii.onTruePart); - IfItem ii2 = ii; - while (true) { - if ((isNeq && (!ii2.onTrue.isEmpty() && (ii2.onTrue.get(0) instanceof IfItem))) - || (!isNeq && (!ii2.onFalse.isEmpty() && (ii2.onFalse.get(0) instanceof IfItem)))) { - ii2 = (IfItem) (isNeq ? ii2.onTrue.get(0) : ii2.onFalse.get(0)); - if ((ii2.expression instanceof StrictNeqActionItem) || (ii2.expression instanceof StrictEqActionItem)) { - isNeq = (ii2.expression instanceof StrictNeqActionItem); - sneq = ((BinaryOpItem) ii2.expression); - if (sneq.leftSide instanceof DirectValueActionItem) { - DirectValueActionItem dv = (DirectValueActionItem) sneq.leftSide; - if (dv.value instanceof RegisterNumber) { - RegisterNumber rn = (RegisterNumber) dv.value; - if (rn.number == regId) { - switchParts.add(ii2.decisionPart); - switchOnFalseParts.add(ii2.onTruePart); - switchExpressions.add(sneq.rightSide); - walkNext.add(isNeq ? ii2.onFalse : ii2.onTrue); + IfItem ii2 = ii; + IfItem lastOkayIi = ii; + while (true) { + if ((isNeq && (!ii2.onTrue.isEmpty() && (ii2.onTrue.get(0) instanceof IfItem))) + || (!isNeq && (!ii2.onFalse.isEmpty() && (ii2.onFalse.get(0) instanceof IfItem)))) { + ii2 = (IfItem) (isNeq ? ii2.onTrue.get(0) : ii2.onFalse.get(0)); + if ((ii2.expression instanceof StrictNeqActionItem) || (ii2.expression instanceof StrictEqActionItem)) { + isNeq = (ii2.expression instanceof StrictNeqActionItem); + sneq = ((BinaryOpItem) ii2.expression); + if (sneq.leftSide instanceof DirectValueActionItem) { + DirectValueActionItem dv = (DirectValueActionItem) sneq.leftSide; + if (dv.value instanceof RegisterNumber) { + RegisterNumber rn = (RegisterNumber) dv.value; + if (rn.number == regId) { + processedIfs.add(ii.decisionPart); + processedIfs.add(ii2.decisionPart); + switchParts.add(ii2.decisionPart); + switchOnFalseParts.add(ii2.onTruePart); + switchExpressions.add(sneq.rightSide); + lastOkayIi = ii2; + } else { + break; + } + } else { + break; + } + } else if (svar != null) { + if (sneq.leftSide.valueEquals(svar)) { + processedIfs.add(ii.decisionPart); + processedIfs.add(ii2.decisionPart); + switchParts.add(ii2.decisionPart); + switchOnFalseParts.add(ii2.onTruePart); + switchExpressions.add(sneq.rightSide); + lastOkayIi = ii2; } else { break; } - } else { - break; - } - } else if (svar != null && sneq.leftSide instanceof GetVariableActionItem) { - if (sneq.leftSide.valueEquals(svar)) { - switchParts.add(ii2.decisionPart); - switchOnFalseParts.add(ii2.onTruePart); - switchExpressions.add(sneq.rightSide); - walkNext.add(isNeq ? ii2.onFalse : ii2.onTrue); } else { break; } @@ -675,29 +687,22 @@ public class ActionGraph extends Graph { } else { break; } - } else { - break; } - } - if (switchParts.size() > 1) { - allSwitchParts.add(switchParts); - allSwitchOnFalseParts.add(switchOnFalseParts); - allSwitchExpressions.add(switchExpressions); - walkNext.add(ii2.onFalse); - canUseBlock = false; + if (switchParts.size() > 1) { + allSwitchParts.add(switchParts); + allSwitchOnFalseParts.add(switchOnFalseParts); + allSwitchExpressions.add(switchExpressions); + } } } } } - if ((item instanceof Block) && (canUseBlock)) { + if ((item instanceof Block)) { for (List sub : ((Block) item).getSubs()) { - checkSecondPassSwitches(sub, allSwitchParts, allSwitchOnFalseParts, allSwitchExpressions); + checkSecondPassSwitches(processedIfs, sub, allSwitchParts, allSwitchOnFalseParts, allSwitchExpressions); } } - for (List next : walkNext) { - checkSecondPassSwitches(next, allSwitchParts, allSwitchOnFalseParts, allSwitchExpressions); - } } } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/CallMethodActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/CallMethodActionItem.java index 3a0b6be13..dedb307f9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/CallMethodActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/CallMethodActionItem.java @@ -71,7 +71,8 @@ public class CallMethodActionItem extends ActionItem { } if (!blankMethod) { - if (scriptObject.getPrecedence() > this.precedence) { + if (scriptObject.getPrecedence() > this.precedence + || ((scriptObject instanceof DirectValueActionItem) && (((DirectValueActionItem) scriptObject).value instanceof Long))) { writer.append("("); scriptObject.toString(writer, localData); writer.append(")"); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetMemberActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetMemberActionItem.java index 509379519..5505ecca2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetMemberActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetMemberActionItem.java @@ -91,7 +91,13 @@ public class SetMemberActionItem extends ActionItem implements SetTypeActionItem @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - object.toString(writer, localData); + if (((object instanceof DirectValueActionItem) && (((DirectValueActionItem) object).value instanceof Long))) { + writer.append("("); + object.toString(writer, localData); + writer.append(")"); + } else { + object.toString(writer, localData); + } if ((!(objectName instanceof DirectValueActionItem)) || (!((DirectValueActionItem) objectName).isString()) || (!IdentifiersDeobfuscation.isValidName(false, ((DirectValueActionItem) objectName).toStringNoQuotes(localData)))) { writer.append("["); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java index dfe7b1577..b83249bcf 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java @@ -263,7 +263,7 @@ public class ActionScript2Parser { return "" + uniqLast; } - private List commands(boolean inFunction, boolean inMethod, int forinlevel, boolean inTellTarget, List variables, List functions, Reference hasEval) throws IOException, ActionParseException { + private List commands(boolean inFunction, boolean inMethod, int forinlevel, boolean inTellTarget, List variables, List functions, Reference hasEval) throws IOException, ActionParseException, InterruptedException { List ret = new ArrayList<>(); if (debugMode) { System.out.println("commands:"); @@ -278,7 +278,7 @@ public class ActionScript2Parser { return ret; } - private GraphTargetItem type(List variables) throws IOException, ActionParseException { + private GraphTargetItem type(List variables) throws IOException, ActionParseException, InterruptedException { GraphTargetItem ret; ParsedSymbol s = lex(); @@ -329,13 +329,16 @@ public class ActionScript2Parser { } } - private ParsedSymbol expectedType(Object... type) throws IOException, ActionParseException { + private ParsedSymbol expectedType(Object... type) throws IOException, ActionParseException, InterruptedException { ParsedSymbol symb = lex(); expected(symb, lexer.yyline(), type); return symb; } - private ParsedSymbol lex() throws IOException, ActionParseException { + private ParsedSymbol lex() throws IOException, ActionParseException, InterruptedException { + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException(); + } ParsedSymbol ret = lexer.lex(); if (debugMode) { System.out.println(ret); @@ -343,7 +346,7 @@ public class ActionScript2Parser { return ret; } - private List call(boolean inFunction, boolean inMethod, boolean inTellTarget, List variables, List functions, Reference hasEval) throws IOException, ActionParseException { + private List call(boolean inFunction, boolean inMethod, boolean inTellTarget, List variables, List functions, Reference hasEval) throws IOException, ActionParseException, InterruptedException { List ret = new ArrayList<>(); //expected(SymbolType.PARENT_OPEN); //MUST BE HANDLED BY CALLER ParsedSymbol s = lex(); @@ -358,7 +361,7 @@ public class ActionScript2Parser { return ret; } - private FunctionActionItem function(boolean withBody, String functionName, boolean isMethod, List variables, List functions, boolean inTellTarget, Reference hasEval) throws IOException, ActionParseException { + private FunctionActionItem function(boolean withBody, String functionName, boolean isMethod, List variables, List functions, boolean inTellTarget, Reference hasEval) throws IOException, ActionParseException, InterruptedException { GraphTargetItem ret = null; ParsedSymbol s; expectedType(SymbolType.PARENT_OPEN); @@ -401,7 +404,7 @@ public class ActionScript2Parser { return retf; } - private GraphTargetItem traits(boolean isInterface, GraphTargetItem nameStr, GraphTargetItem extendsStr, List implementsStr, List variables, List functions, boolean inTellTarget, Reference hasEval) throws IOException, ActionParseException { + private GraphTargetItem traits(boolean isInterface, GraphTargetItem nameStr, GraphTargetItem extendsStr, List implementsStr, List variables, List functions, boolean inTellTarget, Reference hasEval) throws IOException, ActionParseException, InterruptedException { GraphTargetItem ret = null; /*for (int i = 0; i < nameStr.size() - 1; i++) { @@ -543,7 +546,7 @@ public class ActionScript2Parser { } } - private GraphTargetItem expressionCommands(ParsedSymbol s, boolean inFunction, boolean inMethod, boolean inTellTarget, int forinlevel, List variables, List functions, Reference hasEval) throws IOException, ActionParseException { + private GraphTargetItem expressionCommands(ParsedSymbol s, boolean inFunction, boolean inMethod, boolean inTellTarget, int forinlevel, List variables, List functions, Reference hasEval) throws IOException, ActionParseException, InterruptedException { if (debugMode) { System.out.println("expressionCommands:"); } @@ -950,7 +953,7 @@ public class ActionScript2Parser { } } - private GraphTargetItem command(boolean inFunction, boolean inMethod, int forinlevel, boolean inTellTarget, boolean mustBeCommand, List variables, List functions, Reference hasEval) throws IOException, ActionParseException { + private GraphTargetItem command(boolean inFunction, boolean inMethod, int forinlevel, boolean inTellTarget, boolean mustBeCommand, List variables, List functions, Reference hasEval) throws IOException, ActionParseException, InterruptedException { LexBufferer buf = new LexBufferer(); lexer.addListener(buf); GraphTargetItem ret = null; @@ -1375,7 +1378,7 @@ public class ActionScript2Parser { } - private GraphTargetItem expression(boolean inFunction, boolean inMethod, boolean inTellTarget, boolean allowRemainder, List variables, List functions, boolean allowComma, Reference hasEval) throws IOException, ActionParseException { + private GraphTargetItem expression(boolean inFunction, boolean inMethod, boolean inTellTarget, boolean allowRemainder, List variables, List functions, boolean allowComma, Reference hasEval) throws IOException, ActionParseException, InterruptedException { if (debugMode) { System.out.println("expression:"); } @@ -1402,7 +1405,7 @@ public class ActionScript2Parser { return new CommaExpressionItem(null, null, commaItems); } - private ParsedSymbol peekLex() throws IOException, ActionParseException { + private ParsedSymbol peekLex() throws IOException, ActionParseException, InterruptedException { ParsedSymbol lookahead = lex(); lexer.pushback(lookahead); return lookahead; @@ -1435,7 +1438,7 @@ public class ActionScript2Parser { return s.type.getPrecedence(); } - private GraphTargetItem expression1(GraphTargetItem lhs, int min_precedence, boolean inFunction, boolean inMethod, boolean inTellTarget, boolean allowRemainder, List variables, List functions, Reference hasEval) throws IOException, ActionParseException { + private GraphTargetItem expression1(GraphTargetItem lhs, int min_precedence, boolean inFunction, boolean inMethod, boolean inTellTarget, boolean allowRemainder, List variables, List functions, Reference hasEval) throws IOException, ActionParseException, InterruptedException { ParsedSymbol op; GraphTargetItem rhs; GraphTargetItem mhs = null; @@ -1663,7 +1666,7 @@ public class ActionScript2Parser { return (item instanceof VariableActionItem); } - private int brackets(List ret, boolean inFunction, boolean inMethod, boolean inTellTarget, List variables, List functions, Reference hasEval) throws IOException, ActionParseException { + private int brackets(List ret, boolean inFunction, boolean inMethod, boolean inTellTarget, List variables, List functions, Reference hasEval) throws IOException, ActionParseException, InterruptedException { ParsedSymbol s = lex(); int arrCnt = 0; if (s.type == SymbolType.BRACKET_OPEN) { @@ -1687,7 +1690,7 @@ public class ActionScript2Parser { return arrCnt; } - private GraphTargetItem handleVariable(ParsedSymbol s, GraphTargetItem ret, List variables, Reference allowMemberOrCall, boolean inFunction, boolean inMethod, boolean inTellTarget, List functions, Reference hasEval) throws IOException, ActionParseException { + private GraphTargetItem handleVariable(ParsedSymbol s, GraphTargetItem ret, List variables, Reference allowMemberOrCall, boolean inFunction, boolean inMethod, boolean inTellTarget, List functions, Reference hasEval) throws IOException, ActionParseException, InterruptedException { if (s.value.equals("not")) { ret = new NotItem(null, null, expressionPrimary(false, inFunction, inMethod, inTellTarget, false, variables, functions, true, hasEval)); } else { @@ -1710,7 +1713,7 @@ public class ActionScript2Parser { return ret; } - private GraphTargetItem expressionPrimary(boolean allowEmpty, boolean inFunction, boolean inMethod, boolean inTellTarget, boolean allowRemainder, List variables, List functions, boolean allowCall, Reference hasEval) throws IOException, ActionParseException { + private GraphTargetItem expressionPrimary(boolean allowEmpty, boolean inFunction, boolean inMethod, boolean inTellTarget, boolean allowRemainder, List variables, List functions, boolean allowCall, Reference hasEval) throws IOException, ActionParseException, InterruptedException { if (debugMode) { System.out.println("primary:"); } @@ -2008,7 +2011,7 @@ public class ActionScript2Parser { return false; } - private GraphTargetItem memberOrCall(GraphTargetItem ret, boolean inFunction, boolean inMethod, boolean inTellTarget, List variables, List functions, boolean allowCall, Reference hasEval) throws IOException, ActionParseException { + private GraphTargetItem memberOrCall(GraphTargetItem ret, boolean inFunction, boolean inMethod, boolean inTellTarget, List variables, List functions, boolean allowCall, Reference hasEval) throws IOException, ActionParseException, InterruptedException { ParsedSymbol op = lex(); while (op.isType(SymbolType.PARENT_OPEN, SymbolType.BRACKET_OPEN, SymbolType.DOT)) { if (op.type == SymbolType.PARENT_OPEN) { @@ -2100,7 +2103,7 @@ public class ActionScript2Parser { private List constantPool; - public List treeFromString(String str, List constantPool) throws ActionParseException, IOException { + public List treeFromString(String str, List constantPool) throws ActionParseException, IOException, InterruptedException { List retTree = new ArrayList<>(); this.constantPool = constantPool; lexer = new ActionScriptLexer(new StringReader(str)); @@ -2391,7 +2394,7 @@ public class ActionScript2Parser { return ret; } - public List actionsFromString(String s) throws ActionParseException, IOException, CompilationException { + public List actionsFromString(String s) throws ActionParseException, IOException, CompilationException, InterruptedException { try { List constantPool = new ArrayList<>(); List tree = treeFromString(s, constantPool); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/PreviewExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/PreviewExporter.java index 73eb8604c..ca5480541 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/PreviewExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/PreviewExporter.java @@ -179,6 +179,8 @@ public class PreviewExporter { Logger.getLogger(PreviewExporter.class.getName()).log(Level.SEVERE, null, ex); } catch (ActionParseException ex) { Logger.getLogger(PreviewExporter.class.getName()).log(Level.SEVERE, null, ex); + } catch (InterruptedException ex) { + Logger.getLogger(PreviewExporter.class.getName()).log(Level.SEVERE, null, ex); } overVideoButton.actions.add(bca); @@ -205,6 +207,8 @@ public class PreviewExporter { Logger.getLogger(PreviewExporter.class.getName()).log(Level.SEVERE, null, ex); } catch (ActionParseException ex) { Logger.getLogger(PreviewExporter.class.getName()).log(Level.SEVERE, null, ex); + } catch (InterruptedException ex) { + Logger.getLogger(PreviewExporter.class.getName()).log(Level.SEVERE, null, ex); } progressBarButton.actions.add(bca); @@ -238,6 +242,8 @@ public class PreviewExporter { Logger.getLogger(PreviewExporter.class.getName()).log(Level.SEVERE, null, ex); } catch (ActionParseException ex) { Logger.getLogger(PreviewExporter.class.getName()).log(Level.SEVERE, null, ex); + } catch (InterruptedException ex) { + Logger.getLogger(PreviewExporter.class.getName()).log(Level.SEVERE, null, ex); } doAction.writeTag(sos2); @@ -429,8 +435,8 @@ public class PreviewExporter { RECT r = ((BoundedTag) treeItem).getRect(); rxmin = r.Xmin; rymin = r.Ymin; - /*mat.translateX = -r.Xmin; - mat.translateY = -r.Ymin;*/ + mat.translateX = -r.Xmin; + mat.translateY = -r.Ymin; mat.translateX = mat.translateX + width / 2 - r.getWidth() / 2; mat.translateY = mat.translateY + (showControls ? height - progressBarHeight * 20 : height) / 2 - r.getHeight() / 2; } else { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS2ScriptImporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS2ScriptImporter.java index da6974fc8..18f549a7d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS2ScriptImporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS2ScriptImporter.java @@ -41,7 +41,10 @@ public class AS2ScriptImporter { private static final Logger logger = Logger.getLogger(AS2ScriptImporter.class.getName()); - public int importScripts(String scriptsFolder, Map asms) { + public int importScripts(String scriptsFolder, Map asms) throws InterruptedException { + return importScripts(scriptsFolder, asms, null); + } + public int importScripts(String scriptsFolder, Map asms, ScriptImporterProgressListener listener) throws InterruptedException { if (!scriptsFolder.endsWith(File.separator)) { scriptsFolder += File.separator; } @@ -50,6 +53,9 @@ public class AS2ScriptImporter { int importCount = 0; for (String key : asms.keySet()) { + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException(); + } ASMSource asm = asms.get(key); String currentOutDir = scriptsFolder + key + File.separator; currentOutDir = new File(currentOutDir).getParentFile().toString() + File.separator; @@ -71,6 +77,7 @@ public class AS2ScriptImporter { String fileName = Path.combine(currentOutDir, name) + ".as"; if (new File(fileName).exists()) { + asm.getSwf().informListeners("importing_as", fileName); String txt = Helper.readTextFile(fileName); ActionScript2Parser par = new ActionScript2Parser(asm.getSwf(), asm); @@ -82,16 +89,22 @@ public class AS2ScriptImporter { logger.log(Level.SEVERE, "%error% on line %line%, file: %file%".replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)).replace("%file%", fileName), ex); } catch (IOException ex) { logger.log(Level.SEVERE, "error during script import, file: %file%".replace("%file%", fileName), ex); + } catch (InterruptedException ex) { + return importCount; } catch (Exception ex) { logger.log(Level.SEVERE, "error during script import, file: %file%".replace("%file%", fileName), ex); } asm.setModified(); importCount++; + if (listener != null) { + listener.scriptImported(); + } } fileName = Path.combine(currentOutDir, name) + ".pcode"; if (new File(fileName).exists()) { + asm.getSwf().informListeners("importing_as", fileName); String txt = Helper.readTextFile(fileName); try { @@ -104,19 +117,27 @@ public class AS2ScriptImporter { asm.setModified(); importCount++; + if (listener != null) { + listener.scriptImported(); + } } fileName = Path.combine(currentOutDir, name) + ".hex"; if (new File(fileName).exists()) { + asm.getSwf().informListeners("importing_as", fileName); String txt = Helper.readTextFile(fileName); asm.setActionBytes(Helper.getBytesFromHexaText(txt)); asm.setModified(); importCount++; + if (listener != null) { + listener.scriptImported(); + } } fileName = Path.combine(currentOutDir, name) + ".txt"; if (new File(fileName).exists()) { + asm.getSwf().informListeners("importing_as", fileName); String txt = Helper.readTextFile(fileName); try { @@ -126,6 +147,9 @@ public class AS2ScriptImporter { } asm.setModified(); importCount++; + if (listener != null) { + listener.scriptImported(); + } } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS3ScriptImporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS3ScriptImporter.java index 21afe4e50..512ccf581 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS3ScriptImporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS3ScriptImporter.java @@ -34,16 +34,24 @@ public class AS3ScriptImporter { private static final Logger logger = Logger.getLogger(AS3ScriptImporter.class.getName()); - public int importScripts(As3ScriptReplacerInterface scriptReplacer, String scriptsFolder, List packs) { + public int importScripts(As3ScriptReplacerInterface scriptReplacer, String scriptsFolder, List packs) throws InterruptedException { + return importScripts(scriptReplacer, scriptsFolder, packs, null); + } + + public int importScripts(As3ScriptReplacerInterface scriptReplacer, String scriptsFolder, List packs, ScriptImporterProgressListener listener) throws InterruptedException { if (!scriptsFolder.endsWith(File.separator)) { scriptsFolder += File.separator; } int importCount = 0; for (ScriptPack pack : packs) { + if (Thread.currentThread().isInterrupted()) { + return importCount; + } try { File file = pack.getExportFile(scriptsFolder, new ScriptExportSettings(ScriptExportMode.AS, false, false)); if (file.exists()) { + pack.getSwf().informListeners("importing_as", file.getAbsolutePath()); String fileName = file.getAbsolutePath(); String txt = Helper.readTextFile(fileName); @@ -54,10 +62,13 @@ public class AS3ScriptImporter { logger.log(Level.SEVERE, "%error% on line %line%, column %col%, file: %file%".replace("%error%", item.getMessage()).replace("%line%", Long.toString(item.getLine())).replace("%file%", fileName).replace("%col%", "" + item.getCol())); } } catch (InterruptedException ex) { - logger.log(Level.SEVERE, "error during script import, file: %file%".replace("%file%", fileName), ex); + return importCount; } importCount++; + if (listener != null) { + listener.scriptImported(); + } } } catch (IOException ex) { logger.log(Level.SEVERE, null, ex); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/ScriptImporterProgressListener.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/ScriptImporterProgressListener.java new file mode 100644 index 000000000..efa722ad2 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/ScriptImporterProgressListener.java @@ -0,0 +1,9 @@ +package com.jpexs.decompiler.flash.importers; + +/** + * + * @author JPEXS + */ +public interface ScriptImporterProgressListener { + public void scriptImported(); +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontInfo2Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontInfo2Tag.java index 860a3c4e4..357495be9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontInfo2Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontInfo2Tag.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.SWF; @@ -145,6 +146,9 @@ public class DefineFontInfo2Tag extends FontInfoTag { @Override public void addFontCharacter(int index, int character) { + if (character > 255) { + fontFlagsWideCodes = true; + } codeTable.add(index, character); setModified(true); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontInfoTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontInfoTag.java index a97385b99..8966ed84f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontInfoTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontInfoTag.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.SWF; @@ -146,6 +147,9 @@ public class DefineFontInfoTag extends FontInfoTag { @Override public void addFontCharacter(int index, int character) { + if (character > 255) { + fontFlagsWideCodes = true; + } codeTable.add(index, character); setModified(true); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/DepthState.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/DepthState.java index f8a14b7a4..cb35570cd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/DepthState.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/DepthState.java @@ -38,6 +38,7 @@ import java.util.concurrent.atomic.AtomicLong; * @author JPEXS */ public class DepthState { + public int depth = -1; public int characterId = -1; @@ -113,6 +114,7 @@ public class DepthState { time = obj.time; placeObjectTag = obj.placeObjectTag; minPlaceObjectNum = obj.minPlaceObjectNum; + depth = obj.depth; if (sameInstance) { time++; instanceId = obj.instanceId; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java index 73afed9f5..060902951 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java @@ -312,6 +312,7 @@ public class Timeline { DepthState fl = frame.layers.get(depth); if (fl == null) { frame.layers.put(depth, fl = new DepthState(swf, frame)); + fl.depth = depth; } frame.layersChanged = true; fl.placeObjectTag = po; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index c4bf288e9..4c1b29281 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -360,38 +360,6 @@ public class Graph { } } - for (GraphPart p : parts) { - if (loopContinues.contains(p)) { - break; - } - boolean common = true; - for (GraphPart q : parts) { - if (q == p) { - continue; - } - if (!q.leadsTo(localData, this, code, p, loops, throwStates, false /*!!THROW*/)) { - common = false; - break; - } - } - if (common) { - return p; - } - } - - /*loopi: - for (int i = 0; i < parts.size(); i++) { - for (int j = 0; j < parts.size(); j++) { - if (j == i) { - continue; - } - if (parts.get(i).leadsTo(localData, this, code, parts.get(j), loops)) { - parts.remove(i); - i--; - continue loopi; - } - } - }*/ List> reachable = new ArrayList<>(); Set allReachable = new LinkedHashSet<>(); for (GraphPart p : parts) { @@ -404,37 +372,76 @@ public class Graph { allReachable.add(p); allReachable.addAll(r1); } - int maxCommonLevel = 0; - GraphPart maxCommonLevelPart = null; - Set visited = new HashSet<>(); - for (GraphPart p : allReachable) { - if (loopContinues.contains(p)) { - break; - } - if (visited.contains(p)) { + int maxCommonLevel = -1; + GraphPart maxCommonPart = null; + for (GraphPart r : allReachable) { + if (loopContinues.contains(r)) { continue; } - visited.add(p); + boolean common = true; int commonLevel = 0; - for (Set r : reachable) { - if (r.contains(p)) { + for (GraphPart p : parts) { + if (p == r) { + commonLevel++; + continue; + } + if (!p.leadsTo(localData, this, code, r, loops, throwStates, false)) { + common = false; + } else { commonLevel++; } } - //System.err.println("commonlevel of " + p + " is " + commonLevel); - if (commonLevel <= maxCommonLevel) { - continue; - } - maxCommonLevel = commonLevel; - maxCommonLevelPart = p; - } - //System.err.println("maxclevel = " + maxCommonLevel); - //System.err.println("maxclevelpart = " + maxCommonLevelPart); + if (common) { + Stack toProcess = new Stack<>(); + Set visited = new HashSet<>(); + toProcess.addAll(parts); + loopprocess: + while (!toProcess.isEmpty()) { + GraphPart p = toProcess.pop(); + if (p == r) { + continue; + } + + if (loopContinues.contains(p)) { + continue; + } + if (visited.contains(p)) { + continue; + } + visited.add(p); + for (GraphPart n : p.nextParts) { + if (n == r) { + continue; + } + + if (loopContinues.contains(n)) { + continue; + } + if (visited.contains(n)) { + continue; + } + if (!n.leadsTo(localData, this, code, r, loops, throwStates, false)) { + common = false; + break loopprocess; + } + } + toProcess.addAll(p.nextParts); + } + + if (common) { + return r; + } + } + if (commonLevel > maxCommonLevel) { + maxCommonPart = r; + maxCommonLevel = commonLevel; + } + } if (maxCommonLevel <= 1) { return null; } - return maxCommonLevelPart; + return maxCommonPart; } public GraphPart getNextNoJump(GraphPart part, BaseLocalData localData) { @@ -2085,8 +2092,7 @@ public class Graph { output.addAll(ex.getOutput()); for (GraphPart p : allParts) { if (p.containsIP(ex.getIp())) { - if (ipStart == p.start) { - //can this happen? TODO: find some example in the wild + if (ex.getIp() == p.start) { currentRet.addAll(output); //to check for stopparts,etc. we need to call printGraph again part = p; diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2ParserTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2ParserTest.java index cf25cb45d..de9347606 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2ParserTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2ParserTest.java @@ -16,12 +16,15 @@ */ package com.jpexs.decompiler.flash; +import com.jpexs.decompiler.flash.action.parser.ActionParseException; import com.jpexs.decompiler.flash.action.parser.script.ActionScript2Parser; import com.jpexs.decompiler.flash.action.swf4.ActionPush; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.tags.DoActionTag; import com.jpexs.decompiler.graph.CompilationException; import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; import static org.testng.Assert.fail; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -44,7 +47,7 @@ public class ActionScript2ParserTest extends ActionScript2TestBase { swf.version = SWF.DEFAULT_VERSION; ActionScript2Parser par = new ActionScript2Parser(swf, new DoActionTag(swf)); par.actionsFromString(script); - } catch (IOException | CompilationException | ParseException ex) { + } catch (IOException | CompilationException | ParseException | InterruptedException ex) { fail("Unable to parse: " + script, ex); } } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java index 92da81eaa..99060be40 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java @@ -2385,4 +2385,12 @@ public class ActionScript2Test extends ActionScript2TestBase { + "trace(\"after\");\r\n" ); } + + @Test + public void frame85_numbersCallTest() { + compareSrc(85, "trace(\"numbersCallTest\");\r\n" + + "var a = (5).toString();\r\n" + + "var b = 5.2.toString();\r\n" + ); + } } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java index b21478dcc..5a7ab35d3 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java @@ -89,9 +89,9 @@ public abstract class ActionScript3DecompileTestBase extends ActionScriptTestBas try { List ts = new ArrayList<>(); ts.add(abc.instance_info.get(clsIndex).instance_traits); - - Configuration.autoDeobfuscate.set(methodName.toLowerCase().contains("obfus")); - + + Configuration.autoDeobfuscate.set(methodName.toLowerCase().contains("obfus")); + abc.bodies.get(bodyIndex).convert(new ConvertData(), "run", ScriptExportMode.AS, isStatic, abc.bodies.get(bodyIndex).method_info, scriptIndex, clsIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), ts, true, new HashSet<>()); writer = new HighlightedTextWriter(new CodeFormatting(), false); abc.bodies.get(bodyIndex).toString("run", ScriptExportMode.AS, abc, null, writer, new ArrayList<>(), new HashSet<>()); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3OptinalParametersTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3OptinalParametersTest.java index ca29543b3..f15a9c3f0 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3OptinalParametersTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3OptinalParametersTest.java @@ -23,6 +23,7 @@ public class ActionScript3OptinalParametersTest extends ActionScript3DecompileTe public void init() throws IOException, InterruptedException { addSwf("standard", "testdata/as3_new/bin/as3_new.flex.swf"); } + @Test public void testOptionalParameters() { String methodName = "testOptionalParameters"; diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java index e95a32d4a..104812b60 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java @@ -16,6 +16,12 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT addSwf("assembled", "testdata/as3_assembled/bin/as3_assembled.swf"); } + @Test + public void testActivationProps() { + decompileMethod("assembled", "testActivationProps", "var myvar2:int = 10;\r\n", + false); + } + @Test public void testDeclareReg() { decompileMethod("assembled", "testDeclareReg", "with(other)\r\n" diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java index 0ddea2fa7..2e1ae07f1 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java @@ -16,12 +16,32 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile addSwf("classic_air", "testdata/as3_new/bin/as3_new.air.swf"); } + @Test + public void testActivationArguments() { + decompileMethod("classic_air", "testActivationArguments", "var func:Function = function(a:int, b:int):int\r\n" + + "{\r\n" + + "return a + b;\r\n" + + "};\r\n" + + "if(arguments.length > 0)\r\n" + + "{\r\n" + + "trace(arguments[0]);\r\n" + + "}\r\n", + false); + } + @Test public void testArguments() { decompileMethod("classic_air", "testArguments", "return arguments[0];\r\n", false); } + @Test + public void testCallLocal() { + decompileMethod("classic_air", "testCallLocal", "var f:Function = getF();\r\n" + + "var b:int = f(1,3);\r\n", + false); + } + @Test public void testCatchFinally() { decompileMethod("classic_air", "testCatchFinally", "var a:int = 5;\r\n" @@ -870,6 +890,27 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile false); } + @Test + public void testIfFinally() { + decompileMethod("classic_air", "testIfFinally", "var a:int = Math.random();\r\n" + + "if(a == 5)\r\n" + + "{\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try body\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"in finally\");\r\n" + + "}\r\n" + + "}\r\n", + false); + } + @Test public void testIfInIf() { decompileMethod("classic_air", "testIfInIf", "var k:int = 5;\r\n" @@ -1018,7 +1059,6 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile decompileMethod("classic_air", "testInlineFunctions", "var first:String = \"value1\";\r\n" + "var traceParameter:Function = function(aParam:String):String\r\n" + "{\r\n" - + "aParam = aParam;\r\n" + "var second:String = \"value2\";\r\n" + "second = second + \"cc\";\r\n" + "var traceParam2:Function = function(bParam:String):String\r\n" @@ -1036,8 +1076,7 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile @Test public void testInnerFunctionScope() { - decompileMethod("classic_air", "testInnerFunctionScope", "a = a;\r\n" - + "var innerFunc:Function = function(b:String):*\r\n" + decompileMethod("classic_air", "testInnerFunctionScope", "var innerFunc:Function = function(b:String):*\r\n" + "{\r\n" + "testProm = 4;\r\n" + "trace(testProm);\r\n" @@ -1048,8 +1087,7 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile @Test public void testInnerFunctions() { - decompileMethod("classic_air", "testInnerFunctions", "a = a;\r\n" - + "var s:int = 0;\r\n" + decompileMethod("classic_air", "testInnerFunctions", "var s:int = 0;\r\n" + "var innerFunc:Function = function(b:String):*\r\n" + "{\r\n" + "trace(b);\r\n" @@ -1193,6 +1231,20 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile false); } + @Test + public void testNegate() { + decompileMethod("classic_air", "testNegate", "var a:int = 5;\r\n" + + "var b:int = ~a;\r\n", + false); + } + + @Test + public void testNumberCall() { + decompileMethod("classic_air", "testNumberCall", "var a:String = (5).toString();\r\n" + + "var b:String = 5.2.toString();\r\n", + false); + } + @Test public void testParamNames() { decompileMethod("classic_air", "testParamNames", "return firstp + secondp + thirdp;\r\n", @@ -1346,6 +1398,25 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile false); } + @Test + public void testSwitchIf() { + decompileMethod("classic_air", "testSwitchIf", "var code:String = \"4\";\r\n" + + "var a:Boolean = true;\r\n" + + "switch(int(code) - 2)\r\n" + + "{\r\n" + + "case 0:\r\n" + + "if(a)\r\n" + + "{\r\n" + + "trace(\"A\");\r\n" + + "break;\r\n" + + "}\r\n" + + "break;\r\n" + + "case 1:\r\n" + + "}\r\n" + + "trace(\"B\");\r\n", + false); + } + @Test public void testTernarOperator() { decompileMethod("classic_air", "testTernarOperator", "var a:int = 5;\r\n" diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java index 2b5729dd1..28c0350ea 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java @@ -16,12 +16,32 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes addSwf("classic", "testdata/as3_new/bin/as3_new.flex.swf"); } + @Test + public void testActivationArguments() { + decompileMethod("classic", "testActivationArguments", "var func:Function = function(a:int, b:int):int\r\n" + + "{\r\n" + + "return a + b;\r\n" + + "};\r\n" + + "if(arguments.length > 0)\r\n" + + "{\r\n" + + "trace(arguments[0]);\r\n" + + "}\r\n", + false); + } + @Test public void testArguments() { decompileMethod("classic", "testArguments", "return arguments[0];\r\n", false); } + @Test + public void testCallLocal() { + decompileMethod("classic", "testCallLocal", "var f:Function = this.getF();\r\n" + + "var b:int = f(1,3);\r\n", + false); + } + @Test public void testCatchFinally() { decompileMethod("classic", "testCatchFinally", "var a:* = 5;\r\n" @@ -864,6 +884,27 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes false); } + @Test + public void testIfFinally() { + decompileMethod("classic", "testIfFinally", "var a:int = Math.random();\r\n" + + "if(a == 5)\r\n" + + "{\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try body\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"in finally\");\r\n" + + "}\r\n" + + "}\r\n", + false); + } + @Test public void testIfInIf() { decompileMethod("classic", "testIfInIf", "var k:int = 5;\r\n" @@ -1183,6 +1224,20 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes false); } + @Test + public void testNegate() { + decompileMethod("classic", "testNegate", "var a:int = 5;\r\n" + + "var b:int = ~a;\r\n", + false); + } + + @Test + public void testNumberCall() { + decompileMethod("classic", "testNumberCall", "var a:String = (5).toString();\r\n" + + "var b:String = 5.2.toString();\r\n", + false); + } + @Test public void testParamNames() { decompileMethod("classic", "testParamNames", "return firstp + secondp + thirdp;\r\n", @@ -1336,6 +1391,24 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes false); } + @Test + public void testSwitchIf() { + decompileMethod("classic", "testSwitchIf", "var code:String = \"4\";\r\n" + + "var a:Boolean = true;\r\n" + + "switch(int(code) - 2)\r\n" + + "{\r\n" + + "case 0:\r\n" + + "case 1:\r\n" + + "if(a)\r\n" + + "{\r\n" + + "trace(\"A\");\r\n" + + "break;\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"B\");\r\n", + false); + } + @Test public void testTernarOperator() { decompileMethod("classic", "testTernarOperator", "var a:* = 5;\r\n" diff --git a/libsrc/ffdec_lib/testdata/as2/as2.fla b/libsrc/ffdec_lib/testdata/as2/as2.fla index a9896f64e..ebcc85512 100644 Binary files a/libsrc/ffdec_lib/testdata/as2/as2.fla and b/libsrc/ffdec_lib/testdata/as2/as2.fla differ diff --git a/libsrc/ffdec_lib/testdata/as2/as2.swf b/libsrc/ffdec_lib/testdata/as2/as2.swf index a0d770c32..d2e3f2c37 100644 Binary files a/libsrc/ffdec_lib/testdata/as2/as2.swf and b/libsrc/ffdec_lib/testdata/as2/as2.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc index 7a52bbf8e..14763b448 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc and b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc differ diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.asasm index 489896ae4..0f8b76834 100644 --- a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.asasm +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.asasm @@ -29,5 +29,6 @@ program #include "tests/TestSwitchGoto.script.asasm" #include "tests/TestTryWhile.script.asasm" #include "tests/TestPushWhile.script.asasm" + #include "tests/TestActivationProps.script.asasm" ; place to add next end ; program diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestActivationProps.class.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestActivationProps.class.asasm new file mode 100644 index 000000000..0a328bc06 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestActivationProps.class.asasm @@ -0,0 +1,83 @@ +class + refid "tests:TestActivationProps" + instance QName(PackageNamespace("tests"), "TestActivationProps") + extends QName(PackageNamespace(""), "Object") + flag SEALED + flag PROTECTEDNS + protectedns ProtectedNamespace("tests:TestActivationProps") + iinit + refid "tests:TestActivationProps/instance/init" + body + maxstack 1 + localcount 1 + initscopedepth 4 + maxscopedepth 5 + code + getlocal0 + pushscope + + getlocal0 + constructsuper 0 + + returnvoid + end ; code + end ; body + end ; method + trait method QName(PackageNamespace(""), "run") + method + refid "tests:TestActivationProps/instance/run" + flag HAS_OPTIONAL + flag HAS_PARAM_NAMES + flag NEED_ACTIVATION + param QName(PackageNamespace(""),"int") + paramname "myvar" + returns QName(PackageNamespace(""), "void") + body + maxstack 2 + localcount 4 + initscopedepth 4 + maxscopedepth 5 + trait slot QName(PackageInternalNs("testing"),"myvar") + slotid 1 + type QName(PackageNamespace(""),"int") + end ; trait + trait slot QName(PackageInternalNs("testing"),"myvar2") + slotid 2 + type QName(PackageNamespace(""),"int") + end ; trait + code + debug 1, "myvar", 0, 0 + getlocal0 + pushscope + newactivation + dup + setlocal 6 + pushscope + findpropstrict QName(PackageInternalNs("testing"),"myvar") + getlocal1 + setproperty QName(PackageInternalNs("testing"),"myvar") + findpropstrict QName(PackageInternalNs("testing"),"myvar2") + pushbyte 10 + setproperty QName(PackageInternalNs("testing"),"myvar2") + returnvoid + end ; code + end ; body + end ; method + end ; trait + end ; instance + cinit + refid "tests:TestActivationProps/class/init" + body + maxstack 1 + localcount 1 + initscopedepth 3 + maxscopedepth 4 + code + getlocal0 + pushscope + + returnvoid + end ; code + end ; body + end ; method +end ; class diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestActivationProps.script.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestActivationProps.script.asasm new file mode 100644 index 000000000..711260a68 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestActivationProps.script.asasm @@ -0,0 +1,29 @@ +script + sinit + refid "tests:TestActivationProps/init" + body + maxstack 2 + localcount 1 + initscopedepth 1 + maxscopedepth 3 + code + getlocal0 + pushscope + + findpropstrict Multiname("TestActivationProps", [PackageNamespace("tests")]) + getlex QName(PackageNamespace(""), "Object") + pushscope + + getlex Multiname("Object", [PrivateNamespace(null, "tests:TestActivationProps"), PackageNamespace(""), PackageNamespace("tests"), PackageInternalNs("tests"), Namespace("http://adobe.com/AS3/2006/builtin")]) + newclass "tests:TestActivationProps" + popscope + initproperty QName(PackageNamespace("tests"), "TestActivationProps") + + returnvoid + end ; code + end ; body + end ; method + trait class QName(PackageNamespace("tests"), "TestActivationProps") + #include "TestActivationProps.class.asasm" + end ; trait +end ; script diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf b/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf index 6fdb3d7a9..3c7b02db7 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf and b/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf index 2ee129cef..2564af4ef 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf and b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf index 5077763ec..ff926929a 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf and b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_new/obj/as3_newConfig.old b/libsrc/ffdec_lib/testdata/as3_new/obj/as3_newConfig.old index 48bbe0213..09cd1e0d1 100644 --- a/libsrc/ffdec_lib/testdata/as3_new/obj/as3_newConfig.old +++ b/libsrc/ffdec_lib/testdata/as3_new/obj/as3_newConfig.old @@ -16,7 +16,7 @@ CONFIG::timeStamp - '13.03.2021' + '04.12.2021' CONFIG::air diff --git a/libsrc/ffdec_lib/testdata/as3_new/obj/as3_newConfig.xml b/libsrc/ffdec_lib/testdata/as3_new/obj/as3_newConfig.xml index 48bbe0213..09cd1e0d1 100644 --- a/libsrc/ffdec_lib/testdata/as3_new/obj/as3_newConfig.xml +++ b/libsrc/ffdec_lib/testdata/as3_new/obj/as3_newConfig.xml @@ -16,7 +16,7 @@ CONFIG::timeStamp - '13.03.2021' + '04.12.2021' CONFIG::air diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/Main.as b/libsrc/ffdec_lib/testdata/as3_new/src/Main.as index 9f8881045..07f038411 100644 --- a/libsrc/ffdec_lib/testdata/as3_new/src/Main.as +++ b/libsrc/ffdec_lib/testdata/as3_new/src/Main.as @@ -15,7 +15,9 @@ package */ public class Main extends Sprite { + TestActivationArguments; TestArguments; + TestCallLocal; TestCatchFinally; TestChain2; TestChainedAssignments; @@ -58,6 +60,7 @@ package TestHello; TestIf; TestIfElse; + TestIfFinally; TestIfInIf; TestIfTry; TestIgnoreAndOr; @@ -75,6 +78,8 @@ package TestMultipleCondition; TestNamedAnonFunctions; TestNames; + TestNegate; + TestNumberCall; TestOptionalParameters; TestParamNames; TestParamsCount; @@ -89,6 +94,7 @@ package TestSwitch; TestSwitchComma; TestSwitchDefault; + TestSwitchIf; TestTernarOperator; TestTry; TestTryIf; diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestActivationArguments.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestActivationArguments.as new file mode 100644 index 000000000..80843dbad --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestActivationArguments.as @@ -0,0 +1,16 @@ +package tests +{ + + public class TestActivationArguments + { + public function run():* + { + var func:Function = function(a:int, b:int):int { + return a + b; + } + if (arguments.length > 0){ + trace(arguments[0]); + } + } + } +} diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestCallLocal.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestCallLocal.as new file mode 100644 index 000000000..50f69eea6 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestCallLocal.as @@ -0,0 +1,19 @@ +package tests +{ + + public class TestCallLocal + { + public function getF(): Function + { + return function(a:int, b:int):int { + return a + b; + }; + } + + public function run():* + { + var f:Function = getF(); + var b:int = f(1, 3); + } + } +} diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestIfFinally.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestIfFinally.as new file mode 100644 index 000000000..93a515c6c --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestIfFinally.as @@ -0,0 +1,26 @@ +package tests +{ + + public class TestIfFinally + { + public function run():* + { + var a:int = Math.random(); + if (a == 5) + { + try + { + trace("in try body"); + } + catch (e:Error) + { + trace("in catch"); + } + finally + { + trace("in finally"); + } + } + } + } +} diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestNegate.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestNegate.as new file mode 100644 index 000000000..d37887a56 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestNegate.as @@ -0,0 +1,12 @@ +package tests +{ + + public class TestNegate + { + public function run():void + { + var a:int = 5; + var b:int = ~a; + } + } +} diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestNumberCall.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestNumberCall.as new file mode 100644 index 000000000..14eede836 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestNumberCall.as @@ -0,0 +1,12 @@ +package tests +{ + + public class TestNumberCall + { + public function run():* + { + var a:String = (5).toString(); + var b:String = 5.2.toString(); + } + } +} diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestSwitchIf.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestSwitchIf.as new file mode 100644 index 000000000..842d768ac --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestSwitchIf.as @@ -0,0 +1,23 @@ +package tests +{ + + public class TestSwitchIf + { + public function run():* + { + var code:String = "4"; + var a:Boolean = true; + switch(int(code) - 2) + { + case 0: + case 1: + if(a) + { + trace("A"); + break; + } + } + trace("B"); + } + } +} diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java index 60009b02a..95663220a 100644 --- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java +++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java @@ -3498,8 +3498,8 @@ public class CommandLineArgumentParser { private static void parseImportScript(Stack args) { String flexLocation = Configuration.flexSdkLocation.get(); - if (flexLocation.isEmpty() || (!new File(flexLocation).exists())) { - System.err.println("Flex SDK path not set"); + if (Configuration.useFlexAs3Compiler.get() && (flexLocation.isEmpty() || (!new File(flexLocation).exists()))) { + System.err.println("Flex AS3 compiler enabled but Flex SDK path not set"); System.exit(1); } diff --git a/src/com/jpexs/decompiler/flash/gui/DebuggerHandler.java b/src/com/jpexs/decompiler/flash/gui/DebuggerHandler.java index df11ee308..0e8d24223 100644 --- a/src/com/jpexs/decompiler/flash/gui/DebuggerHandler.java +++ b/src/com/jpexs/decompiler/flash/gui/DebuggerHandler.java @@ -518,6 +518,8 @@ public class DebuggerHandler implements DebugConnectionListener { } Main.getMainFrame().getPanel().updateMenu(); + boolean isAS3 = (Main.getMainFrame().getPanel().getCurrentSwf().isAS3()); + //enlog(DebuggerConnection.class); //enlog(DebuggerCommands.class); @@ -611,9 +613,9 @@ public class DebuggerHandler implements DebugConnectionListener { commands.setGetterTimeout(1500); commands.setSetterTimeout(5000); - boolean isAS3 = (Main.getMainFrame().getPanel().getCurrentSwf().isAS3()); con.isAS3 = isAS3; + //Widelines - only AS3, it hangs in AS1/2 and SWD does not support UI32 lines if (isAS3) { con.wideLines = commands.getOption("wide_line_player", "false").equals("true"); @@ -663,9 +665,6 @@ public class DebuggerHandler implements DebugConnectionListener { } } - synchronized (this) { - connected = true; - } con.addMessageListener(new DebugMessageListener() { @Override public void message(InAskBreakpoints message) { @@ -697,17 +696,19 @@ public class DebuggerHandler implements DebugConnectionListener { breakInfo = con.getMessage(InBreakAtExt.class, DebuggerConnection.PREF_RESPONSE_TIMEOUT); breakReason = con.sendMessageWithTimeout(new OutGetBreakReason(con), InBreakReason.class); + int reasonInt = breakReason == null ? 0 : breakReason.reason; + String newBreakScriptName = "unknown"; if (modulePaths.containsKey(message.file)) { newBreakScriptName = modulePaths.get(message.file); - } else if (breakReason.reason != InBreakReason.REASON_SCRIPT_LOADED) { + } else if (reasonInt != InBreakReason.REASON_SCRIPT_LOADED) { Logger.getLogger(DebuggerCommands.class.getName()).log(Level.SEVERE, "Invalid file: {0}", message.file); return; } final String[] reasonNames = new String[]{"unknown", "breakpoint", "watch", "fault", "stopRequest", "step", "halt", "scriptLoaded"}; - String reason = breakReason.reason < reasonNames.length ? reasonNames[breakReason.reason] : reasonNames[0]; + String reason = reasonInt < reasonNames.length ? reasonNames[reasonInt] : reasonNames[0]; Logger.getLogger(DebuggerHandler.class.getName()).log(Level.FINE, "break at {0}:{1}, reason: {2}", new Object[]{newBreakScriptName, message.line, reason}); @@ -717,7 +718,7 @@ public class DebuggerHandler implements DebugConnectionListener { breakIp = message.line; } - if (breakReason.reason == InBreakReason.REASON_SCRIPT_LOADED) { + if (reasonInt == InBreakReason.REASON_SCRIPT_LOADED) { if (!Configuration.debugHalt.get()) { commands.sendContinue(); return; @@ -744,6 +745,17 @@ public class DebuggerHandler implements DebugConnectionListener { } }); + synchronized (this) { + connected = true; + } + if (!isAS3) { + try { + commands.getConnection().writeMessage(new OutRewind(commands.getConnection())); + } catch (IOException ex) { + Logger.getLogger(DebuggerHandler.class.getName()).log(Level.SEVERE, null, ex); + } + } + for (ConnectionListener l : clisteners) { l.connected(); } diff --git a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index b71a697fb..b5ab16dc8 100644 --- a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -2207,6 +2207,12 @@ public final class ImagePanel extends JPanel implements MediaDisplay { first = false; CharacterTag c = swf.getCharacter(ds.characterId); ret.append(c.toString()); + if(ds.depth > 0) { + ret.append(" "); + ret.append(AppStrings.translate("imagePanel.depth")); + ret.append(" "); + ret.append(ds.depth); + } } if (first) { diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index 419c13d3f..c8b9ebaf9 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -196,6 +196,10 @@ public class Main { public static SearchResultsStorage searchResultsStorage = new SearchResultsStorage(); + public static CancellableWorker importWorker = null; + public static CancellableWorker deobfuscatePCodeWorker = null; + public static CancellableWorker swfPrepareWorker = null; + //This method makes file watcher to shut up during our own file saving public static void startSaving(File savedFile) { savedFiles.add(savedFile); @@ -372,13 +376,13 @@ public class Main { private static interface SwfPreparation { - public SWF prepare(SWF swf); + public SWF prepare(SWF swf) throws InterruptedException; } private static class SwfRunPrepare implements SwfPreparation { @Override - public SWF prepare(SWF swf) { + public SWF prepare(SWF swf) throws InterruptedException { if (Configuration.autoOpenLoadedSWFs.get()) { if (!DebuggerTools.hasDebugger(swf)) { DebuggerTools.switchDebugger(swf); @@ -398,8 +402,26 @@ public class Main { } @Override - public SWF prepare(SWF instrSWF) { + public SWF prepare(SWF instrSWF) throws InterruptedException { instrSWF = super.prepare(instrSWF); + + EventListener prepEventListner = new EventListener() { + @Override + public void handleExportingEvent(String type, int index, int count, Object data) { + } + + @Override + public void handleExportedEvent(String type, int index, int count, Object data) { + } + + @Override + public void handleEvent(String event, Object data) { + if (event.equals("inject_debuginfo")) { + startWork(AppStrings.translate("work.injecting_debuginfo") + "..." + (String) data, swfPrepareWorker); + } + } + }; + instrSWF.addEventListener(prepEventListner); try { File fTempFile = new File(instrSWF.getFile()); instrSWF.enableDebugging(true, new File("."), true, doPCode); @@ -423,6 +445,22 @@ public class Main { swfFileName = swfFileName + ".swd"; } File swdFile = new File(swfFileName); + instrSWF.addEventListener(new EventListener() { + @Override + public void handleExportingEvent(String type, int index, int count, Object data) { + } + + @Override + public void handleExportedEvent(String type, int index, int count, Object data) { + } + + @Override + public void handleEvent(String event, Object data) { + if (event.equals("generate_swd")) { + startWork(AppStrings.translate("work.generating_swd") + "..." + (String) data, swfPrepareWorker); + } + } + }); if (doPCode) { instrSWF.generatePCodeSwdFile(swdFile, getPackBreakPoints(true)); } else { @@ -433,11 +471,12 @@ public class Main { } catch (IOException ex) { //ignore, return instrSWF } + instrSWF.removeEventListener(prepEventListner); return instrSWF; } } - private static void prepareSwf(SwfPreparation prep, File toPrepareFile, File origFile, List tempFiles) throws IOException { + private static void prepareSwf(SwfPreparation prep, File toPrepareFile, File origFile, List tempFiles) throws IOException, InterruptedException { SWF instrSWF = null; try (FileInputStream fis = new FileInputStream(toPrepareFile)) { instrSWF = new SWF(fis, toPrepareFile.getAbsolutePath(), origFile == null ? "unknown.swf" : origFile.getName(), false); @@ -517,7 +556,8 @@ public class Main { } catch (IOException ex) { return; - + } catch (InterruptedException ex) { + return; } if (tempFile != null) { synchronized (Main.class) { @@ -567,6 +607,12 @@ public class Main { Main.stopWork(); } + @Override + protected void onStart() { + swfPrepareWorker = this; + } + + @Override protected void done() { synchronized (Main.class) { @@ -1043,9 +1089,15 @@ public class Main { if (event.equals("deobfuscate")) { startWork(AppStrings.translate("work.deobfuscating") + "..." + (String) data, null); } + if (event.equals("deobfuscate_pcode")) { + startWork(AppStrings.translate("work.deobfuscating_pcode") + "..." + (String) data, deobfuscatePCodeWorker); + } if (event.equals("rename")) { startWork(AppStrings.translate("work.renaming") + "..." + (String) data, null); } + if (event.equals("importing_as")) { + startWork(AppStrings.translate("work.importing_as") + "..." + (String) data, importWorker); + } } }); } diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 21ed803ff..c6038ae9a 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -101,6 +101,7 @@ import com.jpexs.decompiler.flash.importers.As3ScriptReplacerInterface; import com.jpexs.decompiler.flash.importers.BinaryDataImporter; import com.jpexs.decompiler.flash.importers.FFDecAs3ScriptReplacer; import com.jpexs.decompiler.flash.importers.ImageImporter; +import com.jpexs.decompiler.flash.importers.ScriptImporterProgressListener; import com.jpexs.decompiler.flash.importers.ShapeImporter; import com.jpexs.decompiler.flash.importers.SwfXmlImporter; import com.jpexs.decompiler.flash.importers.SymbolClassImporter; @@ -2500,18 +2501,56 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { String selFile = Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath(); String scriptsFolder = Path.combine(selFile, ScriptExportSettings.EXPORT_FOLDER_NAME); + final long timeBefore = System.currentTimeMillis(); + new CancellableWorker() { + private int countAs2 = 0; + private int countAs3 = 0; + @Override + public Void doInBackground() throws Exception { + new AS2ScriptImporter().importScripts(scriptsFolder, swf.getASMs(true), new ScriptImporterProgressListener() { + @Override + public void scriptImported() { + countAs2++; + } + }); + new AS3ScriptImporter().importScripts(as3ScriptReplacer, scriptsFolder, swf.getAS3Packs(), new ScriptImporterProgressListener() { + @Override + public void scriptImported() { + countAs3++; + } + } + ); - int countAs2 = new AS2ScriptImporter().importScripts(scriptsFolder, swf.getASMs(true)); - int countAs3 = new AS3ScriptImporter().importScripts(as3ScriptReplacer, scriptsFolder, swf.getAS3Packs()); + if (countAs3 > 0) { + updateClassesList(); + } + return null; + } - if (countAs3 > 0) { - updateClassesList(); - } + @Override + protected void onStart() { + Main.importWorker = this; + Main.startWork(translate("work.importing_as") + "...", this); + } + + @Override + protected void done() { + Main.stopWork(); + long timeAfter = System.currentTimeMillis(); + final long timeMs = timeAfter - timeBefore; + + Main.importWorker = null; + View.execInEventDispatch(() -> { + setStatus(translate("importing_as.finishedin").replace("%time%", Helper.formatTimeSec(timeMs))); + + ViewMessages.showMessageDialog(MainPanel.this, translate("import.script.result").replace("%count%", Integer.toString(countAs2 + countAs3))); + if (countAs2 != 0 || countAs3 != 0) { + reload(true); + } + }); + } + }.execute(); - ViewMessages.showMessageDialog(this, translate("import.script.result").replace("%count%", Integer.toString(countAs2 + countAs3))); - if (countAs2 != 0 || countAs3 != 0) { - reload(true); - } } } @@ -2765,11 +2804,13 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se @Override protected void onStart() { + Main.deobfuscatePCodeWorker = this; Main.startWork(translate("work.deobfuscating") + "...", this); } @Override protected void done() { + Main.deobfuscatePCodeWorker = null; View.execInEventDispatch(() -> { Main.stopWork(); ViewMessages.showMessageDialog(MainPanel.this, translate("work.deobfuscating.complete")); diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index 226b035a9..fcab78552 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -1516,8 +1516,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListeneradobe webpage. Flex SDK can be downloaded on adobe devnet. -config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html +config.group.tip.paths = Download projector and Playerglobal on adobe webpage. Flex SDK can be downloaded on apache web. +config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html https://flex.apache.org/download-binaries.html config.name.playerLocation = 1) Flash Player projector path config.description.playerLocation = Location of standalone flash player executable. Used for Run action. diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_ca.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_ca.properties index 252f5ba85..94088851f 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_ca.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_ca.properties @@ -379,8 +379,8 @@ config.description.lastSessionFileTitles = Cont\u00e9 els t\u00edtols de fitxers config.group.name.paths = Camins config.group.description.paths = Ubicaci\u00f3 dels fitxers necessaris -config.group.tip.paths = Baixa el projector i Playerglobal de la p\u00e0gina web d'Adobe. El Flex SDK es pot baixar de Adobe devnet. -config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html +config.group.tip.paths = Baixa el projector i Playerglobal de la p\u00e0gina web d'Adobe. El Flex SDK es pot baixar de web apache. +config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html https://flex.apache.org/download-binaries.html config.name.playerLocation = 1) Cam\u00ed del projector de Flash Player config.description.playerLocation = Ubicaci\u00f3 de l'executable independent del reproductor de flash. S'utilitza per a l'acci\u00f3 Executa. diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties index 3fdd1c3ff..d7fc6dbe1 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties @@ -363,8 +363,8 @@ config.description.lastSessionFileTitles = Obsahuje titulky souboru z naposledy config.group.name.paths = Cesty config.group.description.paths = Um\u00edst\u011bn\u00ed pot\u0159ebn\u00fdch soubor\u016f -config.group.tip.paths = Stahn\u011bte si projector a Playerglobal na str\u00e1nk\u00e1ch adobe. Flex SDK lze stahnout na webu adobe devnet. -config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html +config.group.tip.paths = Stahn\u011bte si projector a Playerglobal na str\u00e1nk\u00e1ch adobe. Flex SDK lze stahnout na webu apache. +config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html https://flex.apache.org/download-binaries.html config.name.playerLocation = 1) Cesta k Flash Player projectoru config.description.playerLocation = Um\u00edst\u011bn\u00ed spustiteln\u00e9ho flash playeru. Pou\u017e\u00edvan\u00e9 pro akci Spustit. diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_es.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_es.properties index 5ea3bbb28..ca4c3d2dc 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_es.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_es.properties @@ -381,8 +381,8 @@ config.group.name.paths = Rutas config.group.description.paths = Ubicaci\u00f3n de los archivos necesarios #config.group.tip.paths = Usted puede bajar estos archivos desde la p\u00e1gina web de Adobe #TODO: translate again: -config.group.tip.paths = Download projector and Playerglobal on adobe webpage. Flex SDK can be downloaded on adobe devnet. -config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html +config.group.tip.paths = Download projector and Playerglobal on adobe webpage. Flex SDK can be downloaded on apache web. +config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html https://flex.apache.org/download-binaries.html config.name.playerLocation = 1) Ruta de Flash Player projector config.description.playerLocation = Ubicaci\u00f3n del ejecutable aut\u00f3nomo de Flash Player. Utilizado para la acci\u00f3n Correr. diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_fr.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_fr.properties index 02ea745dd..0be208353 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_fr.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_fr.properties @@ -381,8 +381,8 @@ config.group.name.paths = Chemins config.group.description.paths = Location des fichiers demand\u00e9s #config.group.tip.paths = Vous pouvez t\u00e9l\u00e9charger ces fichiers depuis le site web d'Adobe #TODO: translate again: -config.group.tip.paths = Download projector and Playerglobal on adobe webpage. Flex SDK can be downloaded on adobe devnet. -config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html +config.group.tip.paths = Download projector and Playerglobal on adobe webpage. Flex SDK can be downloaded on apache web. +config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html https://flex.apache.org/download-binaries.html config.name.playerLocation = 1) Chemin du lecteur Flash config.description.playerLocation = Location du lecteur autonome de fichier ex\u00e9cutable Flash. Used for Run action. diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_hu.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_hu.properties index c1106f911..cc6a89abd 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_hu.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_hu.properties @@ -381,8 +381,8 @@ config.group.name.paths = \u00datvonalak config.group.description.paths = A sz\u00fcks\u00e9ges f\u00e1jlok el\u00e9rhet\u0151s\u00e9gei #config.group.tip.paths = Ezeket a f\u00e1jlokat az Adobe honlapj\u00e1r\u00f3l t\u00f6ltheti le #TODO: translate again: -config.group.tip.paths = Download projector and Playerglobal on adobe webpage. Flex SDK can be downloaded on adobe devnet. -config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html +config.group.tip.paths = Download projector and Playerglobal on adobe webpage. Flex SDK can be downloaded on apache web. +config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html https://flex.apache.org/download-binaries.html config.name.playerLocation = 1) Flash Player projector \u00fatvonal config.description.playerLocation = Standalone flash player helye. A Futtat\u00e1shoz sz\u00fcks\u00e9ges. diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_it.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_it.properties index 174149b9d..0c9f7e435 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_it.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_it.properties @@ -381,8 +381,8 @@ config.group.name.paths = Percorsi config.group.description.paths = Ubicazione dei file richiesti #config.group.tip.paths = possibile ottenere questi file dal sito Adobe #TODO: translate again: -config.group.tip.paths = Download projector and Playerglobal on adobe webpage. Flex SDK can be downloaded on adobe devnet. -config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html +config.group.tip.paths = Download projector and Playerglobal on adobe webpage. Flex SDK can be downloaded on apache web. +config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html https://flex.apache.org/download-binaries.html config.name.playerLocation = 1) Percorso Flash Player config.description.playerLocation = Posizione eseguibile Flash Player. Utilizzato per l'azione Esegui. diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_ja.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_ja.properties index 41228d44a..6e8383343 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_ja.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_ja.properties @@ -379,8 +379,8 @@ config.description.lastSessionFileTitles = \u524d\u56de\u306e\u30bb\u30c3\u30b7\ config.group.name.paths = \u30d1\u30b9 config.group.description.paths = \u5fc5\u8981\u306a\u30d5\u30a1\u30a4\u30eb\u306e\u5834\u6240 -config.group.tip.paths = projector \u3068 PlayerGlobal \u306f\u3001Adobe \u306e\u30a6\u30a7\u30d6\u30da\u30fc\u30b8 \u304b\u3089\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3067\u304d\u307e\u3059\u3002Flex SDK \u306f adobe devnet \u3067\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3067\u304d\u307e\u3059\u3002 -config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html +config.group.tip.paths = projector \u3068 PlayerGlobal \u306f\u3001Adobe \u306e\u30a6\u30a7\u30d6\u30da\u30fc\u30b8 \u304b\u3089\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3067\u304d\u307e\u3059\u3002Flex SDK \u306f apache web \u3067\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3067\u304d\u307e\u3059\u3002 +config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html https://flex.apache.org/download-binaries.html config.name.playerLocation = 1) Flash Player projector \u306e\u30d1\u30b9 config.description.playerLocation = \u30b9\u30bf\u30f3\u30c9\u30a2\u30ed\u30f3\u306e Flash Player \u5b9f\u884c\u30d5\u30a1\u30a4\u30eb\u306e\u5834\u6240\u3002\u300c\u5b9f\u884c\u300d\u306b\u4f7f\u7528\u3055\u308c\u307e\u3059 diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_sv.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_sv.properties index f6b5049b1..a9f17c408 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_sv.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_sv.properties @@ -379,8 +379,8 @@ config.description.lastSessionFileTitles = Inneh\u00e5ller dom \u00f6ppna fil ti config.group.name.paths = S\u00f6kv\u00e4gar config.group.description.paths = Plats f\u00f6r n\u00f6dv\u00e4ndiga filer -config.group.tip.paths = Ladda ner projector and Playerglobal fr\u00e5n adobe webbsida. Flex SDK kan blir nerladdad fr\u00e5n adobe devnet. -config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html +config.group.tip.paths = Ladda ner projector and Playerglobal fr\u00e5n adobe webbsida. Flex SDK kan blir nerladdad fr\u00e5n apache web. +config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html https://flex.apache.org/download-binaries.html config.name.playerLocation = 1) Flash Player projector s\u00f6kv\u00e4g config.description.playerLocation = Plats f\u00f6r standalone flash player program. Anv\u00e4nds f\u00f6r normalt anv\u00e4ndande. diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_tr.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_tr.properties index c79089539..4d8eaa29f 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_tr.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_tr.properties @@ -621,8 +621,8 @@ config.description.lastSessionFileTitles = Son oturumdaki a\u00e7\u0131lm\u0131\ config.group.name.paths = Yollar config.group.description.paths = Gerekli dosyalar\u0131n yeri -config.group.tip.paths = Projekt\u00f6r\u00fc ve Playerglobal'\u0131 adobe web sayfas\u0131ndan indirin. Flex SDK, adobe devnet adresinden indirilebilir. -config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html +config.group.tip.paths = Projekt\u00f6r\u00fc ve Playerglobal'\u0131 adobe web sayfas\u0131ndan indirin. Flex SDK, apache web adresinden indirilebilir. +config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html https://flex.apache.org/download-binaries.html diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_zh.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_zh.properties index 40cf56432..d80c2dcbf 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_zh.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_zh.properties @@ -379,8 +379,8 @@ config.description.lastSessionFileTitles = \u5305\u542b\u4e0a\u4e00\u4e2a\u4f1a\ config.group.name.paths = \u8def\u5f84 config.group.description.paths = \u6240\u9700\u6587\u4ef6\u4f4d\u7f6e -config.group.tip.paths = \u5728Adobe\u5b98\u7f51\u4e0a\u4e0b\u8f7dPlayer\u548cPlayerGlobal\u3002 Flex SDK\u53ef\u4ee5\u5728adobe devnet\u4e0a\u4e0b\u8f7d\u3002 -config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html +config.group.tip.paths = \u5728Adobe\u5b98\u7f51\u4e0a\u4e0b\u8f7dPlayer\u548cPlayerGlobal\u3002 Flex SDK\u53ef\u4ee5\u5728apache web\u4e0a\u4e0b\u8f7d\u3002 +config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html https://flex.apache.org/download-binaries.html config.name.playerLocation = 1) Flash Player\u76ee\u5f55 config.description.playerLocation = \u72ec\u7acbFlash Player\u53ef\u6267\u884c\u6587\u4ef6\u7684\u4f4d\u7f6e\u3002 \u7528\u4e8e\u8fd0\u884c\u64cd\u4f5c\u3002 diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index 0c54b8e7f..0f0fda234 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -846,4 +846,13 @@ message.info.importSymbolClass = During importing Symbol-Class, you need to sele message.info.importXml = For XML importing, you need a XML file in special format - the format in which FFDec exports.\r\n \ The best way to create such XML file is to export XML from existing SWF first. -tagInfo.dependentFrames = Dependent Frames \ No newline at end of file +tagInfo.dependentFrames = Dependent Frames + +imagePanel.depth = depth: + +work.importing_as = Importing script +importing_as.finishedin = Imported in %time% +work.deobfuscating_pcode = Deobfuscating pcode + +work.injecting_debuginfo = Injecting debug info +work.generating_swd = Generating SWD file \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties index e06c7fab5..ef781ad1b 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties @@ -822,4 +822,13 @@ message.info.importSymbolClass = B\u011bhem importu Symbol-Class mus\u00edte vyb message.info.importXml = Pro XML import je pot\u0159eba XML soubor ve speci\u00e1ln\u00edm form\u00e1tu - form\u00e1tu, ve kter\u00e9m FFDec exportuje.\r\n \ Nejlep\u0161\u00ed zp\u016fsob jak vytvo\u0159it takov\u00e9 XML je exportovat XML z existuj\u00edc\u00edho SWF. -tagInfo.dependentFrames = Z\u00e1visl\u00e9 sn\u00edmky \ No newline at end of file +tagInfo.dependentFrames = Z\u00e1visl\u00e9 sn\u00edmky + +imagePanel.depth = hloubka: + +work.importing_as = Importuji skript +importing_as.finishedin = Importov\u00e1no za %time% +work.deobfuscating_pcode = Deobfuskov\u00e1n\u00ed p-k\u00f3du + +work.injecting_debuginfo = Injektuji lad\u00edc\u00ed informace +work.generating_swd = Generaruji SWD soubor \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java index 3a2807b95..c5c31be45 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java @@ -1241,7 +1241,7 @@ public class TagTreeContextMenu extends JPopupMenu { try { List actions = parser.actionsFromString("class " + dc.toPrintableString(false) + "{}"); doInit.setActions(actions); - } catch (ActionParseException | IOException | CompilationException ex) { + } catch (ActionParseException | IOException | CompilationException | InterruptedException ex) { //ignore }