diff --git a/CHANGELOG.md b/CHANGELOG.md index 7baffa6cb..e116f36f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ All notable changes to this project will be documented in this file. - AS3: return in finally - AS3 docs not correctly displayed under p-code when metadata present - Improper initialization of ActiveX component when Flash not available causing FFDec not start +- #1206 Switch with multiple default clauses ### Changed - AS3 test methods separated to classes 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 6864565c2..62a447687 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 @@ -87,6 +87,7 @@ import com.jpexs.decompiler.graph.model.PopItem; import com.jpexs.decompiler.graph.model.PushItem; import com.jpexs.decompiler.graph.model.SwitchItem; import com.jpexs.decompiler.graph.model.WhileItem; +import com.jpexs.helpers.Reference; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -740,181 +741,17 @@ public class AVM2Graph extends Graph { defaultPart = defaultPart.nextParts.get(0); } - boolean hasDefault = false; - /* - case 4: - case 5: - default: - trace("5 & def"); - ... - case 6: - - */ - //must go backwards to hit case 5, not case 4 - for (int i = caseBodyParts.size() - 1; i >= 0; i--) { - if (caseBodyParts.get(i) == defaultPart) { - DefaultItem di = new DefaultItem(); - caseValuesMap.add(i + 1, di); - caseBodyParts.add(i + 1, defaultPart); - hasDefault = true; - break; - } - } - - if (!hasDefault) { - /* - case 1: - trace("1"); - case 2: - trace("2"); //no break - default: - trace("def"); - ... - case 3: - */ - //must go backwards to hit case 2, not case 1 - for (int i = caseBodyParts.size() - 1; i >= 0; i--) { - if (caseBodyParts.get(i).leadsTo(localData, this, code, defaultPart, loops, new ArrayList<>())) { - DefaultItem di = new DefaultItem(); - caseValuesMap.add(i + 1, di); - caseBodyParts.add(i + 1, defaultPart); - hasDefault = true; - break; - } - } - } - - if (!hasDefault) { - /* - case 1: - trace("1"); - break; - default: - trace("def"); //no break - case 2: - trace("2"); - */ - for (int i = 0; i < caseBodyParts.size(); i++) { - if (defaultPart.leadsTo(localData, this, code, caseBodyParts.get(i), loops, new ArrayList<>())) { - DefaultItem di = new DefaultItem(); - caseValuesMap.add(i, di); - caseBodyParts.add(i, defaultPart); - hasDefault = true; - break; - } - } - } - - if (!hasDefault) { - /* - case 1: - ... - case 2: - ... - default: - trace("def"); - */ - caseValuesMap.add(new DefaultItem()); - caseBodyParts.add(defaultPart); - } - - GraphPart breakPart = getMostCommonPart(localData, caseBodyParts, loops, new ArrayList<>()); - //removeEdgeToFromList(gotoTargets, breakPart); - - List> caseCommands = new ArrayList<>(); - GraphPart next = breakPart; - - GraphTargetItem ti = checkLoop(new ArrayList() /*??*/, next, stopPart, loops); - - //create switch as new loop break command detection to work - currentLoop = new Loop(loops.size(), null, next); - currentLoop.phase = 1; - loops.add(currentLoop); - List valuesMapping = new ArrayList<>(); - List caseBodies = new ArrayList<>(); - for (int i = 0; i < caseValuesMap.size(); i++) { - GraphPart cur = caseBodyParts.get(i); - if (!caseBodies.contains(cur)) { - caseBodies.add(cur); - } - valuesMapping.add(caseBodies.indexOf(cur)); - } - - for (int i = 0; i < caseBodies.size(); i++) { - List currentCaseCommands = new ArrayList<>(); - GraphPart nextCase = next; - if (next != null) { - if (i < caseBodies.size() - 1) { - if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops, new ArrayList<>())) { - currentCaseCommands.add(new BreakItem(null, localData.lineStartInstruction, currentLoop.id)); - } else { - nextCase = caseBodies.get(i + 1); - } - } - } - List stopPart2x = new ArrayList<>(stopPart); - for (GraphPart b : caseBodies) { - if (b != caseBodies.get(i)) { - stopPart2x.add(b); - } - } - if (breakPart != null) { - stopPart2x.add(breakPart); - } - currentCaseCommands.addAll(0, printGraph(foundGotos, gotoTargets, partCodes, partCodePos, localData, stack, allParts, null, caseBodies.get(i), stopPart2x, loops, staticOperation, path)); - if (currentCaseCommands.size() >= 2) { - if (currentCaseCommands.get(currentCaseCommands.size() - 1) instanceof BreakItem) { - if ((currentCaseCommands.get(currentCaseCommands.size() - 2) instanceof ContinueItem) || (currentCaseCommands.get(currentCaseCommands.size() - 2) instanceof BreakItem)) { - currentCaseCommands.remove(currentCaseCommands.size() - 1); - } - } - } - caseCommands.add(currentCaseCommands); - } - - //If the lastone is default empty and alone, remove it - if (!caseCommands.isEmpty()) { - List lastc = caseCommands.get(caseCommands.size() - 1); - if (!lastc.isEmpty() && (lastc.get(lastc.size() - 1) instanceof BreakItem)) { - BreakItem bi = (BreakItem) lastc.get(lastc.size() - 1); - lastc.remove(lastc.size() - 1); - } - if (lastc.isEmpty()) { - int cnt2 = 0; - if (caseValuesMap.get(caseValuesMap.size() - 1) instanceof DefaultItem) { - for (int i = valuesMapping.size() - 1; i >= 0; i--) { - if (valuesMapping.get(i) == caseCommands.size() - 1) { - cnt2++; - } - } - - caseValuesMap.remove(caseValuesMap.size() - 1); - valuesMapping.remove(valuesMapping.size() - 1); - if (cnt2 == 1) { - caseCommands.remove(lastc); - } - } - } - } - //remove last break from last section - if (!caseCommands.isEmpty()) { - List lastc = caseCommands.get(caseCommands.size() - 1); - if (!lastc.isEmpty() && (lastc.get(lastc.size() - 1) instanceof BreakItem)) { - BreakItem bi = (BreakItem) lastc.get(lastc.size() - 1); - lastc.remove(lastc.size() - 1); - } - } ret = new ArrayList<>(); ret.addAll(output); - SwitchItem sti = new SwitchItem(null, switchStartItem, currentLoop, switchedObject, caseValuesMap, caseCommands, valuesMapping); - ret.add(sti); - currentLoop.phase = 2; - if (next != null) { - if (ti != null) { - ret.add(ti); + Reference nextRef = new Reference<>(null); + Reference tiRef = new Reference<>(null); + ret.add(handleSwitch(switchedObject, switchStartItem, foundGotos, gotoTargets, partCodes, partCodePos, allParts, stack, stopPart, loops, localData, staticOperation, path, caseValuesMap, defaultPart, caseBodyParts, nextRef, tiRef)); + if (nextRef.getVal() != null) { + if (tiRef.getVal() != null) { + ret.add(tiRef.getVal()); } else { - ret.addAll(printGraph(foundGotos, gotoTargets, partCodes, partCodePos, localData, stack, allParts, null, next, stopPart, loops, staticOperation, path)); + ret.addAll(printGraph(foundGotos, gotoTargets, partCodes, partCodePos, localData, stack, allParts, null, nextRef.getVal(), stopPart, loops, staticOperation, path)); } } } @@ -1386,13 +1223,21 @@ public class AVM2Graph extends Graph { SetLocalAVM2Item setLocal = (SetLocalAVM2Item) output.get(output.size() - 1); int setLocalIp = InstructionDefinition.getItemIp(avm2LocalData, setLocal);; Set allUsages = new HashSet<>(avm2LocalData.getSetLocalUsages(setLocalIp)); + boolean isOtherSideReg = false; for (GraphTargetItem otherSide : otherSides.values()) { if (otherSide instanceof LocalRegAVM2Item) { LocalRegAVM2Item otherLog = (LocalRegAVM2Item) otherSide; + if (otherLog.regIndex != setLocal.regIndex) { + break; + } int getLocalIp = InstructionDefinition.getItemIp(avm2LocalData, otherLog); allUsages.remove((Integer) getLocalIp); + isOtherSideReg = true; } } + if (!isOtherSideReg) { + return; + } if (allUsages.isEmpty()) { output.remove(output.size() - 1); switchItem.switchedObject = setLocal.value; 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 85f88bb1d..21e060fa3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -57,6 +57,7 @@ import com.jpexs.decompiler.graph.model.WhileItem; import com.jpexs.helpers.Reference; import java.util.ArrayList; import java.util.Collection; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; @@ -66,6 +67,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.Stack; +import java.util.logging.Level; import java.util.logging.Logger; /** @@ -2367,10 +2369,6 @@ public class Graph { List caseValues = new ArrayList<>(); List> caseCommands = new ArrayList<>(); List valueMappings = new ArrayList<>(); - Loop swLoop = new Loop(loops.size(), null, next); - //removeEdgeToFromList(gotoTargets, next); - swLoop.phase = 1; - loops.add(swLoop); boolean first = false; int pos; @@ -2444,7 +2442,7 @@ public class Graph { } //int ignoredBranch = -1; - if (it instanceof IntegerValueTypeItem) { + if ((it instanceof IntegerValueTypeItem) && !(switchedItem instanceof IntegerValueTypeItem)) { defaultBranch = ((IntegerValueTypeItem) it).intValue(); } @@ -2489,10 +2487,15 @@ public class Graph { //This is tied to AS3 switch implementation which has nextparts switched from index 1. TODO: Make more universal GraphPart defaultPart = hasExpr ? part.nextParts.get(1 + defaultBranch) : part.nextParts.get(0); - //int defaultNum = hasExpr ? 1 + defaultBranch : 0; - + List caseBodyParts = new ArrayList<>(); for (int i = 1; i < part.nextParts.size(); i++) { - if (caseExpressions.containsKey(pos)) { + if (!hasExpr) { + if (part.nextParts.get(i) == defaultPart) { + pos++; + continue; + } + caseValues.add(new IntegerValueItem(null, localData.lineStartInstruction, pos)); + } else if (caseExpressions.containsKey(pos)) { GraphTargetItem expr = caseExpressions.get(pos); if (caseCommaCommands.get(pos).size() > 0) { List exprCommaCommands = new ArrayList<>(caseCommaCommands.get(pos)); @@ -2500,110 +2503,26 @@ public class Graph { expr = new CommaExpressionItem(null, expr.lineStartItem, exprCommaCommands); } caseValues.add(expr); - } else if (part.nextParts.get(i) == defaultPart) { - caseValues.add(new DefaultItem()); } else { - caseValues.add(new IntegerValueItem(null, localData.lineStartInstruction, pos)); + pos++; + continue; } + caseBodyParts.add(part.nextParts.get(i)); pos++; } - - first = true; - pos = 0; - List nextCommands = new ArrayList<>(); - for (int i = 1; i < part.nextParts.size(); i++) { - //gotoTargets.remove(new GraphPartEdge(next, part.nextParts.get(i))); - } - for (int i = 1; i < part.nextParts.size(); i++) { - GraphPart p = part.nextParts.get(i); - - /*if (pos == ignoredBranch) { - pos++; - continue; - }*/ - //if (p != defaultPart) - { - if (vis.contains(p)) { - valueMappings.add(caseCommands.size() - 1); - continue; - } - valueMappings.add(caseCommands.size()); - } - List stopPart2 = new ArrayList<>(); - if (next != null) { - stopPart2.add(next); - } else if (!stopPart.isEmpty()) { - stopPart2.add(stopPart.get(stopPart.size() - 1)); - } - for (GraphPart p2 : part.nextParts) { - if (p2 == p) { - continue; - } - if (!stopPart2.contains(p2)) { - stopPart2.add(p2); - } - } - if (next != p) { - //if (p == defaultPart && !defaultCommands.isEmpty()) { - //ignore - //} else - { - TranslateStack s2 = (TranslateStack) stack.clone(); - s2.clear(); - nextCommands = printGraph(foundGotos, gotoTargets, partCodes, partCodePos, visited, prepareBranchLocalData(localData), s2, allParts, part, p, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); - makeAllCommands(nextCommands, s2); - caseCommands.add(nextCommands); - vis.add(p); - } - } else { - caseCommands.add(nextCommands); - } - first = false; - pos++; - } - - //If the lastone is default empty and alone, remove it - if (!caseCommands.isEmpty()) { - List lastc = caseCommands.get(caseCommands.size() - 1); - if (!lastc.isEmpty() && (lastc.get(lastc.size() - 1) instanceof BreakItem)) { - BreakItem bi = (BreakItem) lastc.get(lastc.size() - 1); - if (bi.loopId == swLoop.id) { - lastc.remove(lastc.size() - 1); - } - } - if (lastc.isEmpty()) { - int cnt = 0; - if (caseValues.get(caseValues.size() - 1) instanceof DefaultItem) { - for (int i = valueMappings.size() - 1; i >= 0; i--) { - if (valueMappings.get(i) == caseCommands.size() - 1) { - cnt++; - } - } - if (cnt == 1) { - caseValues.remove(caseValues.size() - 1); - valueMappings.remove(valueMappings.size() - 1); - caseCommands.remove(lastc); - } - } - } - } - //remove last break from last section - if (!caseCommands.isEmpty()) { - List lastc = caseCommands.get(caseCommands.size() - 1); - if (!lastc.isEmpty() && (lastc.get(lastc.size() - 1) instanceof BreakItem)) { - BreakItem bi = (BreakItem) lastc.get(lastc.size() - 1); - if (bi.loopId == swLoop.id) { - lastc.remove(lastc.size() - 1); - } - } - } - SwitchItem sw = new SwitchItem(null, localData.lineStartInstruction, swLoop, switchedItem, caseValues, caseCommands, valueMappings); + Reference nextRef = new Reference<>(null); + Reference tiRef = new Reference<>(null); + SwitchItem sw = handleSwitch(switchedItem, originalSwitchedItem.getSrc(), foundGotos, gotoTargets, partCodes, partCodePos, allParts, stack, stopPart, loops, localData, staticOperation, path, + caseValues, defaultPart, caseBodyParts, nextRef, tiRef); + next = nextRef.getVal(); checkSwitch(localData, sw, caseExpressionOtherSides, currentRet); currentRet.add(sw); - //TADY - swLoop.phase = 2; if (next != null) { - currentRet.addAll(printGraph(foundGotos, gotoTargets, partCodes, partCodePos, visited, localData, stack, allParts, part, next, stopPart, loops, null, staticOperation, path, recursionLevel + 1)); + if (tiRef.getVal() != null) { + ret.add(tiRef.getVal()); + } else { + currentRet.addAll(printGraph(foundGotos, gotoTargets, partCodes, partCodePos, visited, localData, stack, allParts, part, next, stopPart, loops, null, staticOperation, path, recursionLevel + 1)); + } } pos++; } //else @@ -3240,4 +3159,204 @@ public class Graph { removeEdgeToFromList(edges, to); } } + + protected SwitchItem handleSwitch(GraphTargetItem switchedObject, + GraphSourceItem switchStartItem, List foundGotos, List gotoTargets, Map> partCodes, Map partCodePos, Set allParts, TranslateStack stack, List stopPart, List loops, BaseLocalData localData, int staticOperation, String path, + List caseValuesMap, GraphPart defaultPart, List caseBodyParts, Reference nextRef, Reference tiRef) throws InterruptedException { + boolean hasDefault = false; + /* + case 4: + case 5: + default: + trace("5 & def"); + ... + case 6: + + */ + //must go backwards to hit case 5, not case 4 + for (int i = caseBodyParts.size() - 1; i >= 0; i--) { + if (caseBodyParts.get(i) == defaultPart) { + DefaultItem di = new DefaultItem(); + caseValuesMap.add(i + 1, di); + caseBodyParts.add(i + 1, defaultPart); + hasDefault = true; + break; + } + } + + if (!hasDefault) { + /* + case 1: + trace("1"); + case 2: + trace("2"); //no break + default: + trace("def"); + ... + case 3: + */ + //must go backwards to hit case 2, not case 1 + for (int i = caseBodyParts.size() - 1; i >= 0; i--) { + if (caseBodyParts.get(i).leadsTo(localData, this, code, defaultPart, loops, new ArrayList<>())) { + DefaultItem di = new DefaultItem(); + caseValuesMap.add(i + 1, di); + caseBodyParts.add(i + 1, defaultPart); + hasDefault = true; + break; + } + } + } + + if (!hasDefault) { + /* + case 1: + trace("1"); + break; + default: + trace("def"); //no break + case 2: + trace("2"); + */ + for (int i = 0; i < caseBodyParts.size(); i++) { + if (defaultPart.leadsTo(localData, this, code, caseBodyParts.get(i), loops, new ArrayList<>())) { + DefaultItem di = new DefaultItem(); + caseValuesMap.add(i, di); + caseBodyParts.add(i, defaultPart); + hasDefault = true; + break; + } + } + } + + if (!hasDefault) { + /* + case 1: + ... + case 2: + ... + default: + trace("def"); + */ + caseValuesMap.add(new DefaultItem()); + caseBodyParts.add(defaultPart); + } + + GraphPart breakPart = getMostCommonPart(localData, caseBodyParts, loops, new ArrayList<>()); + //removeEdgeToFromList(gotoTargets, breakPart); + + List> caseCommands = new ArrayList<>(); + GraphPart next = breakPart; + + GraphTargetItem ti = checkLoop(new ArrayList() /*??*/, next, stopPart, loops); + + //create switch as new loop break command detection to work + Loop currentLoop = new Loop(loops.size(), null, next); + currentLoop.phase = 1; + loops.add(currentLoop); + List valuesMapping = new ArrayList<>(); + List caseBodies = new ArrayList<>(); + + for (int i = 0; i < caseValuesMap.size(); i++) { + GraphPart cur = caseBodyParts.get(i); + if (!caseBodies.contains(cur)) { + caseBodies.add(cur); + } + } + + //Sort bodies by leadsto to proper handle clauses without a break statement + loopi: + for (int i = 0; i < caseBodies.size(); i++) { + GraphPart b = caseBodies.get(i); + for (int j = i + 1; j < caseBodies.size(); j++) { + GraphPart b2 = caseBodies.get(j); + if (b2.leadsTo(localData, this, code, b, loops, new ArrayList<>())) { + caseBodies.remove(j); + caseBodies.add(i, b2); + i--; + continue loopi; + } else if (j > i + 1) { + if (b.leadsTo(localData, this, code, b2, loops, new ArrayList<>())) { + caseBodies.remove(j); + caseBodies.add(i + 1, b2); + continue loopi; + } + } + } + } + + for (int i = 0; i < caseValuesMap.size(); i++) { + GraphPart cur = caseBodyParts.get(i); + valuesMapping.add(caseBodies.indexOf(cur)); + } + + for (int i = 0; i < caseBodies.size(); i++) { + List currentCaseCommands = new ArrayList<>(); + GraphPart nextCase = next; + if (next != null) { + if (i < caseBodies.size() - 1) { + if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops, new ArrayList<>())) { + currentCaseCommands.add(new BreakItem(null, localData.lineStartInstruction, currentLoop.id)); + } else { + nextCase = caseBodies.get(i + 1); + } + } + } + List stopPart2x = new ArrayList<>(stopPart); + for (GraphPart b : caseBodies) { + if (b != caseBodies.get(i)) { + stopPart2x.add(b); + } + } + if (breakPart != null) { + stopPart2x.add(breakPart); + } + currentCaseCommands.addAll(0, printGraph(foundGotos, gotoTargets, partCodes, partCodePos, localData, stack, allParts, null, caseBodies.get(i), stopPart2x, loops, staticOperation, path)); + if (currentCaseCommands.size() >= 2) { + if (currentCaseCommands.get(currentCaseCommands.size() - 1) instanceof BreakItem) { + if ((currentCaseCommands.get(currentCaseCommands.size() - 2) instanceof ContinueItem) || (currentCaseCommands.get(currentCaseCommands.size() - 2) instanceof BreakItem)) { + currentCaseCommands.remove(currentCaseCommands.size() - 1); + } + } + } + caseCommands.add(currentCaseCommands); + } + + //If the lastone is default empty and alone, remove it + if (!caseCommands.isEmpty()) { + List lastc = caseCommands.get(caseCommands.size() - 1); + if (!lastc.isEmpty() && (lastc.get(lastc.size() - 1) instanceof BreakItem)) { + BreakItem bi = (BreakItem) lastc.get(lastc.size() - 1); + lastc.remove(lastc.size() - 1); + } + if (lastc.isEmpty()) { + int cnt2 = 0; + if (caseValuesMap.get(caseValuesMap.size() - 1) instanceof DefaultItem) { + for (int i = valuesMapping.size() - 1; i >= 0; i--) { + if (valuesMapping.get(i) == caseCommands.size() - 1) { + cnt2++; + } + } + + caseValuesMap.remove(caseValuesMap.size() - 1); + valuesMapping.remove(valuesMapping.size() - 1); + if (cnt2 == 1) { + caseCommands.remove(lastc); + } + } + } + } + //remove last break from last section + if (!caseCommands.isEmpty()) { + List lastc = caseCommands.get(caseCommands.size() - 1); + if (!lastc.isEmpty() && (lastc.get(lastc.size() - 1) instanceof BreakItem)) { + BreakItem bi = (BreakItem) lastc.get(lastc.size() - 1); + lastc.remove(lastc.size() - 1); + } + } + nextRef.setVal(next); + tiRef.setVal(ti); + currentLoop.phase = 2; + return new SwitchItem(null, switchStartItem, currentLoop, switchedObject, caseValuesMap, caseCommands, valuesMapping); + + } } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3Test.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3Test.java index e2702a039..7d97d3e69 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3Test.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3Test.java @@ -315,8 +315,8 @@ public class ActionScript3Test extends ActionScriptTestBase { decompileMethod("standard", "testDefaultNotLastGrouped", "var k:* = 10;\r\n" + "switch(k)\r\n" + "{\r\n" - + "default:\r\n" + "case \"six\":\r\n" + + "default:\r\n" + "trace(\"def and 6\");\r\n" + "case \"five\":\r\n" + "trace(\"def and 6 and 5\");\r\n" @@ -1658,6 +1658,29 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } + @Test + public void testAssembledSwitchDefault() { + decompileMethod("assembled", "testSwitchDefault", "switch(5)\r\n" + + "{\r\n" + + "case 6:\r\n" + + "var _loc2_:int = 6;\r\n" + + "case 0:\r\n" + + "_loc2_ = 0;\r\n" + + "break;\r\n" + + "case 1:\r\n" + + "_loc2_ = 1;\r\n" + + "case 5:\r\n" + + "_loc2_ = 5;\r\n" + + "break;\r\n" + + "case 3:\r\n" + + "_loc2_ = 3;\r\n" + + "break;\r\n" + + "default:\r\n" + + "_loc2_ = 100;\r\n" + + "}\r\n", + false); + } + @Test public void testOptionalParameters() { String methodName = "testOptionalParameters"; diff --git a/libsrc/ffdec_lib/testdata/custom/abc/custom-0/custom-0.main.abc b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/custom-0.main.abc index 3ab0989ca..1515ac50b 100644 Binary files a/libsrc/ffdec_lib/testdata/custom/abc/custom-0/custom-0.main.abc and b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/custom-0.main.abc differ diff --git a/libsrc/ffdec_lib/testdata/custom/abc/custom-0/custom-0.main.asasm b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/custom-0.main.asasm index 0d8d531be..803f110ed 100644 --- a/libsrc/ffdec_lib/testdata/custom/abc/custom-0/custom-0.main.asasm +++ b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/custom-0.main.asasm @@ -14,6 +14,6 @@ program #include "tests/TestDoubleDup.script.asasm" #include "tests/TestIncrement3.script.asasm" #include "tests/TestDup.script.asasm" - #include "tests/TestDup2.script.asasm" + #include "tests/TestSwitchDefault.script.asasm" ; place to add next end ; program diff --git a/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestDup2.script.asasm b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestDup2.script.asasm deleted file mode 100644 index dc90d4b71..000000000 --- a/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestDup2.script.asasm +++ /dev/null @@ -1,29 +0,0 @@ -script - sinit - refid "tests:TestDup2/init" - body - maxstack 2 - localcount 1 - initscopedepth 1 - maxscopedepth 3 - code - getlocal0 - pushscope - - findpropstrict Multiname("TestDup2", [PackageNamespace("tests")]) - getlex QName(PackageNamespace(""), "Object") - pushscope - - getlex Multiname("Object", [PrivateNamespace(null, "tests:TestDup2"), PackageNamespace(""), PackageNamespace("tests"), PackageInternalNs("tests"), Namespace("http://adobe.com/AS3/2006/builtin")]) - newclass "tests:TestDup2" - popscope - initproperty QName(PackageNamespace("tests"), "TestDup2") - - returnvoid - end ; code - end ; body - end ; method - trait class QName(PackageNamespace("tests"), "TestDup2") - #include "TestDup2.class.asasm" - end ; trait -end ; script diff --git a/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestDup2.class.asasm b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestSwitchDefault.class.asasm similarity index 55% rename from libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestDup2.class.asasm rename to libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestSwitchDefault.class.asasm index 3d6a375c5..a18e2ea7e 100644 --- a/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestDup2.class.asasm +++ b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestSwitchDefault.class.asasm @@ -1,12 +1,12 @@ class - refid "tests:TestDup2" - instance QName(PackageNamespace("tests"), "TestDup2") + refid "tests:TestSwitchDefault" + instance QName(PackageNamespace("tests"), "TestSwitchDefault") extends QName(PackageNamespace(""), "Object") flag SEALED flag PROTECTEDNS - protectedns ProtectedNamespace("tests:TestDup2") + protectedns ProtectedNamespace("tests:TestSwitchDefault") iinit - refid "tests:TestDup2/instance/init" + refid "tests:TestSwitchDefault/instance/init" body maxstack 1 localcount 1 @@ -25,7 +25,7 @@ class end ; method trait method QName(PackageNamespace(""), "run") method - refid "tests:TestDup2/instance/run" + refid "tests:TestSwitchDefault/instance/run" returns QName(PackageNamespace(""), "void") body maxstack 2 @@ -35,14 +35,34 @@ class code getlocal0 pushscope - getlocal3 - getproperty QName(PackageNamespace(""),"myprop") - dup - getlocal1 - getproperty MultinameL([PrivateNamespace("somens")]) - swap - call 0 - pop + + pushbyte 5 + lookupswitch Ldef, [L0,L1,Ldef,L3,Ldef,L5,L6] + Ldef: + pushbyte 100 + setlocal2 + jump Lbr +L0: + pushbyte 0 + setlocal2 + jump Lbr +L1: + pushbyte 1 + setlocal2 + jump L5 +L3: + pushbyte 3 + setlocal2 + jump Lbr +L5: + pushbyte 5 + setlocal2 + jump Lbr +L6: + pushbyte 6 + setlocal2 + jump L0 +Lbr: returnvoid end ; code end ; body @@ -50,7 +70,7 @@ class end ; trait end ; instance cinit - refid "tests:TestDup2/class/init" + refid "tests:TestSwitchDefault/class/init" body maxstack 1 localcount 1 diff --git a/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestSwitchDefault.script.asasm b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestSwitchDefault.script.asasm new file mode 100644 index 000000000..2083f7feb --- /dev/null +++ b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestSwitchDefault.script.asasm @@ -0,0 +1,29 @@ +script + sinit + refid "tests:TestSwitchDefault/init" + body + maxstack 2 + localcount 1 + initscopedepth 1 + maxscopedepth 3 + code + getlocal0 + pushscope + + findpropstrict Multiname("TestSwitchDefault", [PackageNamespace("tests")]) + getlex QName(PackageNamespace(""), "Object") + pushscope + + getlex Multiname("Object", [PrivateNamespace(null, "tests:TestSwitchDefault"), PackageNamespace(""), PackageNamespace("tests"), PackageInternalNs("tests"), Namespace("http://adobe.com/AS3/2006/builtin")]) + newclass "tests:TestSwitchDefault" + popscope + initproperty QName(PackageNamespace("tests"), "TestSwitchDefault") + + returnvoid + end ; code + end ; body + end ; method + trait class QName(PackageNamespace("tests"), "TestSwitchDefault") + #include "TestSwitchDefault.class.asasm" + end ; trait +end ; script diff --git a/libsrc/ffdec_lib/testdata/custom/bin/custom.swf b/libsrc/ffdec_lib/testdata/custom/bin/custom.swf index a5dc7b94e..b68c1f2b3 100644 Binary files a/libsrc/ffdec_lib/testdata/custom/bin/custom.swf and b/libsrc/ffdec_lib/testdata/custom/bin/custom.swf differ