mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-02 11:54:36 +00:00
Fixed AS2 - getters and setters decompilation and editing
Fixed AS1/2 - definefunction2 suppresssuper parameter
This commit is contained in:
@@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.action.model.GetVariableActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.ImplementsOpActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.NewMethodActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.NewObjectActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.ReturnActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.SetMemberActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.SetVariableActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem;
|
||||
@@ -40,6 +41,7 @@ import com.jpexs.decompiler.graph.model.IfItem;
|
||||
import com.jpexs.decompiler.graph.model.NotItem;
|
||||
import com.jpexs.decompiler.graph.model.PopItem;
|
||||
import com.jpexs.decompiler.graph.model.PushItem;
|
||||
import com.jpexs.decompiler.graph.model.ScriptEndItem;
|
||||
import com.jpexs.helpers.Reference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -504,7 +506,19 @@ public class ActionScript2ClassDetector {
|
||||
if (!(getterNameStr.equals("__get__" + propertyNameStr))) {
|
||||
throw new AssertException("getter does not match property name");
|
||||
}
|
||||
//TODO: handle getter HERE
|
||||
|
||||
for (MyEntry<GraphTargetItem, GraphTargetItem> trait : traits) {
|
||||
if (trait.getKey() instanceof DirectValueActionItem) {
|
||||
if (((DirectValueActionItem) trait.getKey()).isString()) {
|
||||
if (((DirectValueActionItem) trait.getKey()).toString().equals(getterNameStr)) {
|
||||
if (trait.getValue() instanceof FunctionActionItem) {
|
||||
FunctionActionItem func = (FunctionActionItem) trait.getValue();
|
||||
func.isGetter = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (propertyGetter instanceof FunctionActionItem) {
|
||||
FunctionActionItem getterFunc = (FunctionActionItem) propertyGetter;
|
||||
@@ -525,7 +539,38 @@ public class ActionScript2ClassDetector {
|
||||
if (!(setterNameStr.equals("__set__" + propertyNameStr))) {
|
||||
throw new AssertException("setter does not match property name");
|
||||
}
|
||||
//TODO: handle setter HERE
|
||||
|
||||
for (MyEntry<GraphTargetItem, GraphTargetItem> trait : traits) {
|
||||
if (trait.getKey() instanceof DirectValueActionItem) {
|
||||
if (((DirectValueActionItem) trait.getKey()).isString()) {
|
||||
if (((DirectValueActionItem) trait.getKey()).toString().equals(setterNameStr)) {
|
||||
if (trait.getValue() instanceof FunctionActionItem) {
|
||||
FunctionActionItem func = (FunctionActionItem) trait.getValue();
|
||||
func.isSetter = true;
|
||||
|
||||
//There is return getter added at the end of every setter, gotta remove it, since it won't compile
|
||||
//as setter must not return a value
|
||||
if (!func.actions.isEmpty()) {
|
||||
int pos = func.actions.size() - 1;
|
||||
if (func.actions.get(pos) instanceof ScriptEndItem) {
|
||||
pos--;
|
||||
}
|
||||
if (pos >= 0 && func.actions.get(pos) instanceof ReturnActionItem) {
|
||||
GraphTargetItem val = func.actions.get(pos);
|
||||
if (val.value instanceof CallMethodActionItem) {
|
||||
if (((CallMethodActionItem) val.value).methodName instanceof DirectValueActionItem) {
|
||||
if (((CallMethodActionItem) val.value).methodName.toString().startsWith("__get__")) {
|
||||
func.actions.remove(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (propertySetter instanceof FunctionActionItem) {
|
||||
FunctionActionItem setterFunc = (FunctionActionItem) propertySetter;
|
||||
if (!(setterFunc.actions.isEmpty() && setterFunc.functionName.isEmpty() && ((FunctionActionItem) propertySetter).paramNames.isEmpty())) {
|
||||
|
||||
@@ -51,6 +51,10 @@ import java.util.Set;
|
||||
*/
|
||||
public class FunctionActionItem extends ActionItem implements BranchStackResistant {
|
||||
|
||||
public boolean isGetter = false;
|
||||
|
||||
public boolean isSetter = false;
|
||||
|
||||
public List<GraphTargetItem> actions;
|
||||
|
||||
public List<String> constants;
|
||||
@@ -92,6 +96,10 @@ public class FunctionActionItem extends ActionItem implements BranchStackResista
|
||||
|
||||
}
|
||||
|
||||
public void addVariable(VariableActionItem variable) {
|
||||
variables.add(variable);
|
||||
}
|
||||
|
||||
|
||||
public FunctionActionItem() {
|
||||
super(null, null, PRECEDENCE_PRIMARY);
|
||||
@@ -119,21 +127,43 @@ public class FunctionActionItem extends ActionItem implements BranchStackResista
|
||||
srcData.localName = n;
|
||||
srcData.declaration = true;
|
||||
}
|
||||
|
||||
writer.append("function");
|
||||
if (isGetter) {
|
||||
writer.append(" get");
|
||||
}
|
||||
if (isSetter) {
|
||||
writer.append(" set");
|
||||
}
|
||||
if (calculatedFunctionName != null) {
|
||||
writer.append(" ");
|
||||
String fname = calculatedFunctionName.toStringNoQuotes(localData);
|
||||
if (isGetter && fname.startsWith("__get__")) {
|
||||
fname = fname.substring(7);
|
||||
}
|
||||
if (isSetter && fname.startsWith("__set__")) {
|
||||
fname = fname.substring(7);
|
||||
}
|
||||
|
||||
if (!IdentifiersDeobfuscation.isValidName(false, fname)) {
|
||||
IdentifiersDeobfuscation.appendObfuscatedIdentifier(fname, writer);
|
||||
} else {
|
||||
calculatedFunctionName.appendToNoQuotes(writer, localData);
|
||||
writer.append(fname);
|
||||
//calculatedFunctionName.appendToNoQuotes(writer, localData);
|
||||
}
|
||||
} else if (!functionName.isEmpty()) {
|
||||
String fname = functionName;
|
||||
if (isGetter && fname.startsWith("__get__")) {
|
||||
fname = fname.substring(7);
|
||||
}
|
||||
if (isSetter && fname.startsWith("__set__")) {
|
||||
fname = fname.substring(7);
|
||||
}
|
||||
writer.append(" ");
|
||||
if (!IdentifiersDeobfuscation.isValidName(false, functionName)) {
|
||||
IdentifiersDeobfuscation.appendObfuscatedIdentifier(functionName, writer);
|
||||
if (!IdentifiersDeobfuscation.isValidName(false, fname)) {
|
||||
IdentifiersDeobfuscation.appendObfuscatedIdentifier(fname, writer);
|
||||
} else {
|
||||
writer.append(functionName);
|
||||
writer.append(fname);
|
||||
}
|
||||
}
|
||||
writer.spaceBeforeCallParenthesies(paramNames.size());
|
||||
@@ -262,7 +292,7 @@ public class FunctionActionItem extends ActionItem implements BranchStackResista
|
||||
boolean preloadThisFlag = false;
|
||||
boolean preloadGlobalFlag = false;
|
||||
|
||||
boolean suppressParentFlag = false;
|
||||
boolean suppressSuperFlag = false;
|
||||
boolean suppressArgumentsFlag = false;
|
||||
boolean suppressThisFlag = false;
|
||||
|
||||
@@ -288,7 +318,10 @@ public class FunctionActionItem extends ActionItem implements BranchStackResista
|
||||
preloadSuperFlag = true;
|
||||
needsFun2 = true;
|
||||
registerNames.add("super");
|
||||
} else {
|
||||
suppressSuperFlag = true;
|
||||
}
|
||||
|
||||
if (usedNames.contains("_root")) {
|
||||
preloadRootFlag = true;
|
||||
needsFun2 = true;
|
||||
@@ -298,8 +331,6 @@ public class FunctionActionItem extends ActionItem implements BranchStackResista
|
||||
preloadParentFlag = true;
|
||||
needsFun2 = true;
|
||||
registerNames.add("_parent");
|
||||
} else {
|
||||
suppressParentFlag = true;
|
||||
}
|
||||
if (usedNames.contains("_global")) {
|
||||
needsFun2 = true;
|
||||
@@ -404,7 +435,7 @@ public class FunctionActionItem extends ActionItem implements BranchStackResista
|
||||
ret.add(0, new ActionDefineFunction2(functionName,
|
||||
preloadParentFlag,
|
||||
preloadRootFlag,
|
||||
suppressParentFlag,
|
||||
suppressSuperFlag,
|
||||
preloadSuperFlag,
|
||||
suppressArgumentsFlag,
|
||||
preloadArgumentsFlag,
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.action.parser.script;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.CallMethodAVM2Item;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.model.AsciiToCharActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.CallActionItem;
|
||||
@@ -447,6 +448,8 @@ public class ActionScript2Parser {
|
||||
looptrait:
|
||||
while (true) {
|
||||
s = lex();
|
||||
boolean isGetter = false;
|
||||
boolean isSetter = false;
|
||||
boolean isStatic = false;
|
||||
while (s.isType(SymbolType.STATIC, SymbolType.PUBLIC, SymbolType.PRIVATE)) {
|
||||
if (s.type == SymbolType.STATIC) {
|
||||
@@ -457,6 +460,15 @@ public class ActionScript2Parser {
|
||||
switch (s.type) {
|
||||
case FUNCTION:
|
||||
s = lex();
|
||||
|
||||
if (s.type == SymbolType.SET) {
|
||||
isSetter = true;
|
||||
s = lex();
|
||||
} else if (s.type == SymbolType.GET) {
|
||||
isGetter = true;
|
||||
s = lex();
|
||||
}
|
||||
|
||||
expectedIdentifier(s, lexer.yyline());
|
||||
String fname = s.value.toString();
|
||||
if (fname.equals(classNameStr)) { //constructor
|
||||
@@ -466,16 +478,37 @@ public class ActionScript2Parser {
|
||||
if (isStatic) {
|
||||
FunctionActionItem ft = function(!isInterface, "", true, variables, functions, inTellTarget, hasEval);
|
||||
ft.calculatedFunctionName = pushConst(fname);
|
||||
ft.isSetter = isSetter;
|
||||
ft.isGetter = isGetter;
|
||||
//staticFunctions.add(ft);
|
||||
traits.add(new MyEntry<>(ft.calculatedFunctionName, ft));
|
||||
traitsStatic.add(true);
|
||||
|
||||
if (isSetter) {
|
||||
//add return getter automatically
|
||||
GraphTargetItem callM = new CallMethodActionItem(null, null, nameStr, pushConst("__get__" + fname), new ArrayList<>());
|
||||
GraphTargetItem retV = new ReturnActionItem(null, null, callM);
|
||||
ft.actions.add(retV);
|
||||
}
|
||||
} else {
|
||||
FunctionActionItem ft = function(!isInterface, "", true, variables, functions, inTellTarget, hasEval);
|
||||
ft.calculatedFunctionName = pushConst(fname);
|
||||
ft.isSetter = isSetter;
|
||||
ft.isGetter = isGetter;
|
||||
//instanceFunctions.add(ft);
|
||||
traits.add(new MyEntry<>(ft.calculatedFunctionName, ft));
|
||||
traitsStatic.add(false);
|
||||
|
||||
if (isSetter) {
|
||||
//add return getter automatically
|
||||
GraphTargetItem thisVar = new VariableActionItem("this", null, false);
|
||||
ft.addVariable((VariableActionItem) thisVar);
|
||||
GraphTargetItem callM = new CallMethodActionItem(null, null, thisVar, pushConst("__get__" + fname), new ArrayList<>());
|
||||
GraphTargetItem retV = new ReturnActionItem(null, null, callM);
|
||||
ft.actions.add(retV);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case VAR:
|
||||
@@ -651,6 +684,7 @@ public class ActionScript2Parser {
|
||||
SymbolType.EACH, SymbolGroup.GLOBALFUNC,
|
||||
SymbolType.NUMBER_OP, SymbolType.STRING_OP);
|
||||
}
|
||||
|
||||
private void expectedIdentifier(ParsedSymbol s, int line, Object... exceptions) throws IOException, ActionParseException {
|
||||
for (Object ex : exceptions) {
|
||||
if (s.isType(ex)) {
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ConstantIndex;
|
||||
import com.jpexs.decompiler.flash.action.swf4.RegisterNumber;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionCallMethod;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionGetMember;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionNewObject;
|
||||
@@ -70,7 +71,10 @@ import com.jpexs.decompiler.graph.model.WhileItem;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -711,6 +715,16 @@ public class ActionSourceGenerator implements SourceGenerator {
|
||||
constr.add(new ActionStoreRegister(1));
|
||||
constr = (typeToActions(globalClassTypeStr, constr));
|
||||
}
|
||||
|
||||
Set<String> properties = new LinkedHashSet<>();
|
||||
Set<String> setters = new HashSet<>();
|
||||
Set<String> getters = new HashSet<>();
|
||||
|
||||
Set<String> staticProperties = new LinkedHashSet<>();
|
||||
Set<String> staticSetters = new HashSet<>();
|
||||
Set<String> staticGetters = new HashSet<>();
|
||||
|
||||
|
||||
if (!isInterface) {
|
||||
for (int pass = 1; pass <= 2; pass++) { //two passes, methods first, then variables
|
||||
for (int t = 0; t < traits.size(); t++) {
|
||||
@@ -721,8 +735,20 @@ public class ActionSourceGenerator implements SourceGenerator {
|
||||
boolean isFunc = (en.getValue() instanceof FunctionActionItem);
|
||||
if (pass == 1 && isFunc) { //Add methods in first pass
|
||||
FunctionActionItem fi = (FunctionActionItem) en.getValue();
|
||||
if (fi.isGetter || fi.isSetter) {
|
||||
(traitsStatic.get(t) ? staticProperties : properties).add(fi.calculatedFunctionName.toString());
|
||||
}
|
||||
String prefix = "";
|
||||
if (fi.isGetter) {
|
||||
(traitsStatic.get(t) ? staticGetters : getters).add(fi.calculatedFunctionName.toString());
|
||||
prefix = "__get__";
|
||||
}
|
||||
if (fi.isSetter) {
|
||||
(traitsStatic.get(t) ? staticSetters : setters).add(fi.calculatedFunctionName.toString());
|
||||
prefix = "__set__";
|
||||
}
|
||||
ifbody.add(new ActionPush(new RegisterNumber(traitsStatic.get(t) ? 1 : 2)));
|
||||
ifbody.add(pushConst(getName(en.getKey())));
|
||||
ifbody.add(pushConst(prefix + getName(en.getKey())));
|
||||
ifbody.addAll(toActionList(fi.toSource(localData, this)));
|
||||
ifbody.add(new ActionSetMember());
|
||||
} else if (pass == 2 && !isFunc) { //add variables in second pass
|
||||
@@ -735,6 +761,41 @@ public class ActionSourceGenerator implements SourceGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
for (String prop : staticProperties) {
|
||||
if (staticSetters.contains(prop)) {
|
||||
ifbody.add(new ActionPush(new Object[]{new RegisterNumber(1), "__set__" + prop}));
|
||||
ifbody.add(new ActionGetMember());
|
||||
} else {
|
||||
ifbody.add(new ActionDefineFunction("", new ArrayList<String>(), 0, swfVersion));
|
||||
}
|
||||
if (staticGetters.contains(prop)) {
|
||||
ifbody.add(new ActionPush(new Object[]{new RegisterNumber(1), "__get__" + prop}));
|
||||
ifbody.add(new ActionGetMember());
|
||||
} else {
|
||||
ifbody.add(new ActionDefineFunction("", new ArrayList<String>(), 0, swfVersion));
|
||||
}
|
||||
ifbody.add(new ActionPush(new Object[]{prop, 3, new RegisterNumber(1), "addProperty"}));
|
||||
ifbody.add(new ActionCallMethod());
|
||||
}
|
||||
|
||||
for (String prop : properties) {
|
||||
if (setters.contains(prop)) {
|
||||
ifbody.add(new ActionPush(new Object[]{new RegisterNumber(2), "__set__" + prop}));
|
||||
ifbody.add(new ActionGetMember());
|
||||
} else {
|
||||
ifbody.add(new ActionDefineFunction("", new ArrayList<String>(), 0, swfVersion));
|
||||
}
|
||||
if (getters.contains(prop)) {
|
||||
ifbody.add(new ActionPush(new Object[]{new RegisterNumber(2), "__get__" + prop}));
|
||||
ifbody.add(new ActionGetMember());
|
||||
} else {
|
||||
ifbody.add(new ActionDefineFunction("", new ArrayList<String>(), 0, swfVersion));
|
||||
}
|
||||
ifbody.add(new ActionPush(new Object[]{prop, 3, new RegisterNumber(2), "addProperty"}));
|
||||
ifbody.add(new ActionCallMethod());
|
||||
}
|
||||
|
||||
|
||||
if (!isInterface) {
|
||||
ifbody.add(new ActionPush((Long) 1L));
|
||||
ifbody.add(new ActionPush(Null.INSTANCE));
|
||||
|
||||
Reference in New Issue
Block a user