AS3 - some simplifications

This commit is contained in:
Jindra Petřík
2016-02-17 19:43:13 +01:00
parent 253f5392c7
commit 6a8d73c798
25 changed files with 157 additions and 59 deletions

View File

@@ -72,6 +72,8 @@ public class AVM2LocalData extends BaseLocalData {
public AVM2Code code;
public boolean thisHasDefaultToPrimitive;
public AVM2LocalData() {
}
@@ -94,6 +96,7 @@ public class AVM2LocalData extends BaseLocalData {
ip = localData.ip;
refs = localData.refs;
code = localData.code;
thisHasDefaultToPrimitive = localData.thisHasDefaultToPrimitive;
}
public AVM2ConstantPool getConstants() {

View File

@@ -1480,7 +1480,7 @@ public class AVM2Code implements Cloneable {
return pos2adr(fixIPAfterDebugLine(adr2pos(addr, true)));
}
public ConvertOutput toSourceOutput(Reference<GraphSourceItem> lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, ABC abc, MethodBody body, int start, int end, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, boolean[] visited, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs) throws ConvertException, InterruptedException {
public ConvertOutput toSourceOutput(boolean thisHasDefaultToPrimitive, Reference<GraphSourceItem> lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, ABC abc, MethodBody body, int start, int end, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, boolean[] visited, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs) throws ConvertException, InterruptedException {
calcKilledStats(body);
boolean debugMode = DEBUG_MODE;
if (debugMode) {
@@ -1585,12 +1585,12 @@ public class AVM2Code implements Cloneable {
AVM2Instruction insAfter = code.get(ip + 1);
if ((insAfter.definition instanceof GetLocalTypeIns) && (((GetLocalTypeIns) insAfter.definition).getRegisterId(insAfter) == ((SetLocalTypeIns) ins.definition).getRegisterId(ins))) {
GraphTargetItem before = stack.peek();
ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this);
ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
stack.push(before);
ip += 2;
continue iploop;
} else {
ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this);
ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
ip++;
continue iploop;
}
@@ -1599,7 +1599,7 @@ public class AVM2Code implements Cloneable {
do {
AVM2Instruction insAfter = ip + 1 < code.size() ? code.get(ip + 1) : null;
if (insAfter == null) {
ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this);
ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
ip++;
break;
}
@@ -1633,7 +1633,7 @@ public class AVM2Code implements Cloneable {
if (((GetLocalTypeIns) code.get(t).definition).getRegisterId(code.get(t)) == reg) {
if (code.get(t + 1).definition instanceof KillIns) {
if (code.get(t + 1).operands[0] == reg) {
ConvertOutput assignment = toSourceOutput(lineStartItem, path, part, processJumps, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, abc, body, ip + 2, t - 1, localRegNames, fullyQualifiedNames, visited, localRegAssigmentIps, refs);
ConvertOutput assignment = toSourceOutput(thisHasDefaultToPrimitive, lineStartItem, path, part, processJumps, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, abc, body, ip + 2, t - 1, localRegNames, fullyQualifiedNames, visited, localRegAssigmentIps, refs);
if (!assignment.output.isEmpty()) {
GraphTargetItem tar = assignment.output.remove(assignment.output.size() - 1);
tar.firstPart = part;
@@ -1667,21 +1667,21 @@ public class AVM2Code implements Cloneable {
}
stack.push(vx);
} else {
ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this);
ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
}
ip++;
break;
//}
} else {
ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this);
ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
ip++;
break;
//throw new ConvertException("Unknown pattern after DUP:" + insComparsion.toString());
}
} while (ins.definition instanceof DupIns);
} else if ((ins.definition instanceof ReturnValueIns) || (ins.definition instanceof ReturnVoidIns) || (ins.definition instanceof ThrowIns)) {
ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this);
ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
//ip = end + 1;
break;
} else if (ins.definition instanceof NewFunctionIns) {
@@ -1717,13 +1717,13 @@ public class AVM2Code implements Cloneable {
}
}
// What to do when hasDup is false?
ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this);
ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
NewFunctionAVM2Item nft = (NewFunctionAVM2Item) stack.peek();
nft.functionName = functionName;
ip++;
} else {
try {
ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this);
ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
} catch (RuntimeException re) {
/*String last="";
int len=5;
@@ -1944,7 +1944,7 @@ public class AVM2Code implements Cloneable {
}*/
}
public List<GraphTargetItem> toGraphTargetItems(ConvertData convertData, String path, int methodIndex, boolean isStatic, int scriptIndex, int classIndex, ABC abc, MethodBody body, HashMap<Integer, String> localRegNames, ScopeStack scopeStack, int initializerType, List<DottedChain> fullyQualifiedNames, List<Traits> initTraits, int staticOperation, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs) throws InterruptedException {
public List<GraphTargetItem> toGraphTargetItems(boolean thisHasDefaultToPrimitive, ConvertData convertData, String path, int methodIndex, boolean isStatic, int scriptIndex, int classIndex, ABC abc, MethodBody body, HashMap<Integer, String> localRegNames, ScopeStack scopeStack, int initializerType, List<DottedChain> fullyQualifiedNames, List<Traits> initTraits, int staticOperation, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs) throws InterruptedException {
initToSource();
List<GraphTargetItem> list;
HashMap<Integer, GraphTargetItem> localRegs = new HashMap<>();
@@ -1955,7 +1955,7 @@ public class AVM2Code implements Cloneable {
}
//try {
list = AVM2Graph.translateViaGraph(path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, fullyQualifiedNames, staticOperation, localRegAssigmentIps, refs);
list = AVM2Graph.translateViaGraph(path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, fullyQualifiedNames, staticOperation, localRegAssigmentIps, refs, thisHasDefaultToPrimitive);
if (initTraits != null) {
loopi:

View File

@@ -105,10 +105,11 @@ public class AVM2Graph extends Graph {
}
public static List<GraphTargetItem> translateViaGraph(String path, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, ScopeStack scopeStack, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, int staticOperation, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs) throws InterruptedException {
public static List<GraphTargetItem> translateViaGraph(String path, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, ScopeStack scopeStack, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, int staticOperation, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs, boolean thisHasDefaultToPrimitive) throws InterruptedException {
AVM2Graph g = new AVM2Graph(code, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, fullyQualifiedNames, localRegAssigmentIps, refs);
AVM2LocalData localData = new AVM2LocalData();
localData.thisHasDefaultToPrimitive = thisHasDefaultToPrimitive;
localData.isStatic = isStatic;
localData.classIndex = classIndex;
localData.localRegs = localRegs;

View File

@@ -105,7 +105,7 @@ public class AVM2GraphSource extends GraphSource {
List<GraphTargetItem> ret = new ArrayList<>();
ScopeStack newstack = ((AVM2LocalData) localData).scopeStack;
Reference<GraphSourceItem> lineStartItem = new Reference<>(localData.lineStartInstruction);
ConvertOutput co = code.toSourceOutput(lineStartItem, path, part, false, isStatic, scriptIndex, classIndex, localRegs, stack, newstack, abc, body, start, end, localRegNames, fullyQualifiedNames, new boolean[size()], localRegAssigmentIps, refs);
ConvertOutput co = code.toSourceOutput(((AVM2LocalData) localData).thisHasDefaultToPrimitive, lineStartItem, path, part, false, isStatic, scriptIndex, classIndex, localRegs, stack, newstack, abc, body, start, end, localRegNames, fullyQualifiedNames, new boolean[size()], localRegAssigmentIps, refs);
localData.lineStartInstruction = lineStartItem.getVal();
ret.addAll(co.output);
return ret;

View File

@@ -40,6 +40,7 @@ import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.ScopeStack;
import com.jpexs.decompiler.graph.TranslateStack;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -145,7 +146,7 @@ public abstract class InstructionDefinition implements Serializable {
public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List<GraphTargetItem> output, String path) throws InterruptedException {
}
public void translate(Reference<GraphSourceItem> lineStartItem, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2Instruction ins, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) throws InterruptedException {
public void translate(Reference<GraphSourceItem> lineStartItem, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2Instruction ins, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code, boolean thisHasDefaultToPrimitive) throws InterruptedException {
AVM2LocalData localData = new AVM2LocalData();
localData.isStatic = isStatic;
localData.scriptIndex = scriptIndex;
@@ -161,6 +162,7 @@ public abstract class InstructionDefinition implements Serializable {
localData.ip = ip;
localData.refs = refs;
localData.code = code;
localData.thisHasDefaultToPrimitive = thisHasDefaultToPrimitive;
translate(localData, stack, ins, output, path);
lineStartItem.setVal(localData.lineStartInstruction);
}
@@ -198,7 +200,7 @@ public abstract class InstructionDefinition implements Serializable {
}
}
return new FullMultinameAVM2Item(property, ins, localData.lineStartInstruction, multinameIndex, name, ns);
return new FullMultinameAVM2Item(property, ins, localData.lineStartInstruction, multinameIndex, localData.abc.constants.getMultiname(multinameIndex).getName(localData.getConstants(), new ArrayList<>(), true), name, ns);
}
protected int getMultinameRequiredStackSize(AVM2ConstantPool constants, int multinameIndex) {

View File

@@ -41,8 +41,8 @@ public class AddIns extends InstructionDefinition {
@Override
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
Object right = lda.operandStack.pop();
Object left = lda.operandStack.pop();
Object right = EcmaScript.toPrimitive(lda.operandStack.pop(), "");
Object left = EcmaScript.toPrimitive(lda.operandStack.pop(), "");
if (EcmaScript.type(left) == EcmaType.STRING || EcmaScript.type(right) == EcmaType.STRING) {
String ret = EcmaScript.toString(left) + EcmaScript.toString(right);
lda.operandStack.push(ret);

View File

@@ -69,22 +69,7 @@ public abstract class GetLocalTypeIns extends InstructionDefinition {
} else {
List<Trait> ts = localData.getInstanceInfo().get(localData.classIndex).instance_traits.traits;
boolean isBasicObject = true;
if (!"Object".equals(localData.getConstants().getMultiname(localData.getInstanceInfo().get(localData.classIndex).super_index).getNameWithNamespace(localData.getConstants()).toRawString())) {
//TODO: check for toString and valueOf in parent object
isBasicObject = false;
} else {
for (Trait t : ts) {
if (t instanceof TraitMethodGetterSetter) {
if ("toString".equals(t.getName(localData.abc).getName(localData.getConstants(), new ArrayList<>(), true))) {
isBasicObject = false;
}
if ("valueOf".equals(t.getName(localData.abc).getName(localData.getConstants(), new ArrayList<>(), true))) {
isBasicObject = false;
}
}
}
}
boolean isBasicObject = localData.thisHasDefaultToPrimitive;
Multiname m = localData.getInstanceInfo().get(localData.classIndex).getName(localData.getConstants());
stack.push(new ThisAVM2Item(ins, localData.lineStartInstruction, m, m.getNameWithNamespace(localData.getConstants()), isBasicObject));
}

View File

@@ -29,6 +29,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.GetPropertyAVM2Item;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.ecma.ArrayType;
import com.jpexs.decompiler.flash.ecma.EcmaScript;
import com.jpexs.decompiler.flash.ecma.EcmaType;
import com.jpexs.decompiler.flash.ecma.ObjectType;
import com.jpexs.decompiler.flash.ecma.Undefined;
import com.jpexs.decompiler.graph.GraphTargetItem;
@@ -50,6 +51,7 @@ public class GetPropertyIns extends InstructionDefinition {
if (constants.getMultiname(ins.operands[0]).kind == Multiname.MULTINAMEL) {
String name = EcmaScript.toString(lda.operandStack.pop());
Object obj = lda.operandStack.pop();
if (obj == ArrayType.EMPTY_ARRAY) {
if ("length".equals(name)) {
lda.operandStack.push(0L);

View File

@@ -26,8 +26,10 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.operations.AsTypeAVM2Item;
import com.jpexs.decompiler.flash.ecma.NotCompileTime;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.TranslateStack;
import java.util.ArrayList;
import java.util.List;
/**
@@ -55,7 +57,7 @@ public class AsTypeIns extends InstructionDefinition {
public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List<GraphTargetItem> output, String path) {
GraphTargetItem val = stack.pop();
stack.push(new AsTypeAVM2Item(ins, localData.lineStartInstruction, val, new FullMultinameAVM2Item(false, ins, localData.lineStartInstruction, ins.operands[0])));
stack.push(new AsTypeAVM2Item(ins, localData.lineStartInstruction, val, new FullMultinameAVM2Item(false, ins, localData.lineStartInstruction, ins.operands[0], localData.abc.constants.getMultiname(ins.operands[0]).getName(localData.getConstants(), new ArrayList<>(), true))));
}
@Override

View File

@@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.operations.IsTypeAVM2Item;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.TranslateStack;
import java.util.ArrayList;
import java.util.List;
/**
@@ -41,7 +42,7 @@ public class IsTypeIns extends InstructionDefinition {
public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List<GraphTargetItem> output, String path) {
int multinameIndex = ins.operands[0];
GraphTargetItem value = stack.pop();
stack.push(new IsTypeAVM2Item(ins, localData.lineStartInstruction, value, new FullMultinameAVM2Item(false, ins, localData.lineStartInstruction, multinameIndex)));
stack.push(new IsTypeAVM2Item(ins, localData.lineStartInstruction, value, new FullMultinameAVM2Item(false, ins, localData.lineStartInstruction, multinameIndex, localData.abc.constants.getMultiname(multinameIndex).getName(localData.getConstants(), new ArrayList<>(), true))));
}
@Override

View File

@@ -16,6 +16,7 @@
*/
package com.jpexs.decompiler.flash.abc.avm2.model;
import com.jpexs.decompiler.graph.model.Callable;
import com.jpexs.decompiler.flash.ecma.EcmaScript;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.GraphSourceItem;

View File

@@ -67,7 +67,7 @@ public class CoerceAVM2Item extends AVM2Item {
return false;
}
dependencies.add(value);
return value.isCompileTime(dependencies);
return value.isConvertedCompileTime(dependencies);
}
@Override
@@ -81,10 +81,7 @@ public class CoerceAVM2Item extends AVM2Item {
if (ret == Undefined.INSTANCE) {
return Null.INSTANCE;
}
if (ret == null) {
return null;
}
return ret.toString();
return value.getResultAsString();
case "*":
break;
}

View File

@@ -66,7 +66,7 @@ public class ConvertAVM2Item extends AVM2Item {
case "uint":
return EcmaScript.toUint32(value.getResult());
case "String":
return value.getResult().toString();
return value.getResultAsString();
case "Object":
return value.getResult(); //if not object throw TypeError
default:
@@ -80,7 +80,7 @@ public class ConvertAVM2Item extends AVM2Item {
return false;
}
dependencies.add(value);
return value.isCompileTime(dependencies);
return value.isConvertedCompileTime(dependencies);
}
@Override

View File

@@ -42,28 +42,33 @@ public class FullMultinameAVM2Item extends AVM2Item {
public boolean property;
public FullMultinameAVM2Item(boolean property, GraphSourceItem instruction, GraphSourceItem lineStartIns, int multinameIndex, GraphTargetItem name) {
public String resolvedMultinameName;
public FullMultinameAVM2Item(boolean property, GraphSourceItem instruction, GraphSourceItem lineStartIns, int multinameIndex, String resolvedMultinameName, GraphTargetItem name) {
super(instruction, lineStartIns, PRECEDENCE_PRIMARY);
this.multinameIndex = multinameIndex;
this.name = name;
this.namespace = null;
this.property = property;
this.resolvedMultinameName = resolvedMultinameName;
}
public FullMultinameAVM2Item(boolean property, GraphSourceItem instruction, GraphSourceItem lineStartIns, int multinameIndex) {
public FullMultinameAVM2Item(boolean property, GraphSourceItem instruction, GraphSourceItem lineStartIns, int multinameIndex, String resolvedMultinameName) {
super(instruction, lineStartIns, PRECEDENCE_PRIMARY);
this.multinameIndex = multinameIndex;
this.resolvedMultinameName = resolvedMultinameName;
this.name = null;
this.namespace = null;
this.property = property;
}
public FullMultinameAVM2Item(boolean property, GraphSourceItem instruction, GraphSourceItem lineStartIns, int multinameIndex, GraphTargetItem name, GraphTargetItem namespace) {
public FullMultinameAVM2Item(boolean property, GraphSourceItem instruction, GraphSourceItem lineStartIns, int multinameIndex, String resolvedMultinameName, GraphTargetItem name, GraphTargetItem namespace) {
super(instruction, lineStartIns, PRECEDENCE_PRIMARY);
this.multinameIndex = multinameIndex;
this.name = name;
this.namespace = namespace;
this.property = property;
this.resolvedMultinameName = resolvedMultinameName;
}
public boolean isRuntime() {

View File

@@ -20,11 +20,15 @@ import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
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.parser.script.AVM2SourceGenerator;
import com.jpexs.decompiler.flash.ecma.EcmaScript;
import com.jpexs.decompiler.flash.ecma.EcmaType;
import com.jpexs.decompiler.flash.ecma.ObjectType;
import com.jpexs.decompiler.flash.ecma.Undefined;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.CompilationException;
import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.SimpleValue;
import com.jpexs.decompiler.graph.SourceGenerator;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.LocalData;
@@ -41,8 +45,30 @@ public class GetPropertyAVM2Item extends AVM2Item {
public GraphTargetItem propertyName;
@Override
public boolean isConvertedCompileTime(Set<GraphTargetItem> dependencies) {
if (object != null && object.isCompileTime() && (propertyName instanceof FullMultinameAVM2Item) && (((FullMultinameAVM2Item) propertyName).name != null) && (((FullMultinameAVM2Item) propertyName).name.isCompileTime()) && "constructor".equals(((FullMultinameAVM2Item) propertyName).name.getResult())) {
Object obj = object.getResult();
EcmaType t = EcmaScript.type(obj);
if (t != EcmaType.OBJECT) {
if (t.getClassName() != null) {
//Note: it's for toString only :-(
return true;
}
}
if (obj instanceof ObjectType) {
//Note: it's for toString only :-(
return true;
}
}
return isCompileTime(dependencies);
}
@Override
public boolean isCompileTime(Set<GraphTargetItem> dependencies) {
if ((object instanceof SimpleValue) && (((SimpleValue) object).isSimpleValue())) {
return true;
}
if (object instanceof NewArrayAVM2Item) {
if (((NewArrayAVM2Item) object).values.isEmpty()) {
return true;
@@ -56,8 +82,30 @@ public class GetPropertyAVM2Item extends AVM2Item {
return false;
}
@Override
public String getResultAsString() {
if (object.isCompileTime() && (propertyName instanceof FullMultinameAVM2Item) && (((FullMultinameAVM2Item) propertyName).name.isCompileTime()) && "constructor".equals(((FullMultinameAVM2Item) propertyName).name.getResult())) {
Object obj = object.getResult();
EcmaType t = EcmaScript.type(obj);
if (t != EcmaType.OBJECT) {
if (t.getClassName() != null) {
return "[class " + t.getClassName() + "]";
}
}
if (obj instanceof ObjectType) {
return "[class " + ((ObjectType) obj).getTypeName() + "]";
}
}
return super.getResultAsString();
}
@Override
public Object getResult() {
Object ores = object.getResult();
EcmaType type = EcmaScript.type(ores);
if (type != EcmaType.OBJECT && (propertyName instanceof FullMultinameAVM2Item) && (((FullMultinameAVM2Item) propertyName).resolvedMultinameName != null)) {
return type.getProperty(ores, ((FullMultinameAVM2Item) propertyName).resolvedMultinameName);
}
if (object instanceof NewArrayAVM2Item) {
if (((NewArrayAVM2Item) object).values.isEmpty()) {
return Undefined.INSTANCE;

View File

@@ -1,5 +1,6 @@
package com.jpexs.decompiler.flash.abc.avm2.model;
import com.jpexs.decompiler.graph.model.Callable;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;

View File

@@ -68,8 +68,10 @@ public class AddAVM2Item extends BinaryOpItem {
public Object getResult() {
Object leftResult = leftSide.getResult();
Object rightResult = rightSide.getResult();
leftResult = EcmaScript.toPrimitive(leftResult, "");
rightResult = EcmaScript.toPrimitive(rightResult, "");
if (EcmaScript.type(leftResult) == EcmaType.STRING || EcmaScript.type(rightResult) == EcmaType.STRING) {
return "" + leftResult + rightResult;
return EcmaScript.toString(leftResult) + EcmaScript.toString(rightResult);
}
return EcmaScript.toNumber(leftResult) + EcmaScript.toNumber(rightResult);
}

View File

@@ -31,6 +31,8 @@ public class ConvertData {
public Map<TraitSlotConst, AssignedValue> assignedValues = new HashMap<>();
public boolean thisHasDefaultToPrimitive;
public ConvertData() {
deobfuscationMode = Configuration.autoDeobfuscate.get() ? 1 : 0;
}

View File

@@ -310,7 +310,7 @@ public final class MethodBody implements Cloneable {
HashMap<Integer, String> localRegNames = getLocalRegNames(abc);
List<GraphTargetItem> convertedItems1;
try (Statistics s = new Statistics("AVM2Code.toGraphTargetItems")) {
convertedItems1 = converted.getCode().toGraphTargetItems(convertData, path, methodIndex, isStatic, scriptIndex, classIndex, abc, converted, localRegNames, scopeStack, initializerType, fullyQualifiedNames, initTraits, Graph.SOP_USE_STATIC, new HashMap<>(), converted.getCode().visitCode(converted));
convertedItems1 = converted.getCode().toGraphTargetItems(convertData.thisHasDefaultToPrimitive, convertData, path, methodIndex, isStatic, scriptIndex, classIndex, abc, converted, localRegNames, scopeStack, initializerType, fullyQualifiedNames, initTraits, Graph.SOP_USE_STATIC, new HashMap<>(), converted.getCode().visitCode(converted));
}
try (Statistics s = new Statistics("Graph.graphToString")) {
Graph.graphToString(convertedItems1, writer, LocalData.create(abc.constants, localRegNames, fullyQualifiedNames));

View File

@@ -17,6 +17,7 @@
package com.jpexs.decompiler.flash.abc.types.traits;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing;
import com.jpexs.decompiler.flash.abc.types.ClassInfo;
import com.jpexs.decompiler.flash.abc.types.ConvertData;
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
@@ -28,6 +29,7 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.decompiler.graph.ScopeStack;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.helpers.Helper;
import java.util.ArrayList;
import java.util.List;
@@ -219,6 +221,10 @@ public class TraitClass extends Trait implements TraitWithSlot {
String instanceInfoName = instanceInfo.getName(abc.constants).getName(abc.constants, fullyQualifiedNames, false);
ClassInfo classInfo = abc.class_info.get(class_info);
AbcIndexing index = new AbcIndexing(abc.getSwf());
//for simplification of String(this)
convertData.thisHasDefaultToPrimitive = null == index.findProperty(new AbcIndexing.PropertyDef("toString", new TypeItem(instanceInfo.getName(abc.constants).getNameWithNamespace(abc.constants)), abc, abc.constants.getNamespaceId(Namespace.KIND_PACKAGE, DottedChain.TOPLEVEL, abc.constants.getStringId("", true), true)), false, true);
//class initializer
int bodyIndex = abc.findBodyIndex(classInfo.cinit_index);
if (bodyIndex != -1) {

View File

@@ -112,9 +112,10 @@ public class EcmaScript {
//TODO: logic similar to 8.12.8
return o.call("toString", new ArrayList<>());
case "Number":
default:
//TODO: logic similar to 8.12.8
return o.call("valueOf", new ArrayList<>());
default:
return o.toPrimitive();
}
}

View File

@@ -12,19 +12,46 @@
* 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.ecma;
import com.jpexs.decompiler.graph.model.Callable;
/**
*
* @author JPEXS
*/
public enum EcmaType {
NULL,
STRING,
NUMBER,
UNDEFINED,
OBJECT,
NULL(null),
STRING("String"),
NUMBER("Number"),
UNDEFINED(null),
OBJECT("Object"),
BOOLEAN("Boolean");
private String clsName;
private EcmaType(String clsName) {
this.clsName = clsName;
}
public String getClassName() {
return clsName;
}
public Object getProperty(Object val, String propName) {
String cls = getClassName();
if (cls == null) {
return null;
}
if ("String".equals(cls)) {
switch (propName) {
case "length":
return EcmaScript.toString(val).length();
}
}
return null;
}
}

View File

@@ -16,7 +16,7 @@
*/
package com.jpexs.decompiler.flash.ecma;
import com.jpexs.decompiler.flash.abc.avm2.model.Callable;
import com.jpexs.decompiler.graph.model.Callable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -57,7 +57,15 @@ public class ObjectType implements Callable {
@Override
public String toString() {
return "[object Object]";
return "[object " + getTypeName() + "]";
}
public String getTypeName() {
return "Object";
}
public Object toPrimitive() {
return toString();
}
@Override

View File

@@ -386,6 +386,10 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
return EcmaScript.toNumberAs2(getResult());
}
public String getResultAsString() {
return EcmaScript.toString(getResult());
}
public String toStringNoQuotes(LocalData localData) {
// todo: honfika: this method should not be called, maybe we should throw an exception
return toString();

View File

@@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.model;
package com.jpexs.decompiler.graph.model;
import java.util.List;