mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-04 09:34:20 +00:00
Issue #1063 AS3 direct edit - script initializer fix, generating method names
XML export/import fixes Interfaces added to AS3 tests
This commit is contained in:
@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.abc.types.Decimal;
|
||||
import com.jpexs.decompiler.flash.abc.types.Multiname;
|
||||
import com.jpexs.decompiler.flash.abc.types.Namespace;
|
||||
import com.jpexs.decompiler.flash.abc.types.NamespaceSet;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Internal;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.helpers.utf8.Utf8PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
@@ -50,6 +51,7 @@ public class AVM2ConstantPool implements Cloneable {
|
||||
|
||||
public List<Multiname> constant_multiname = new ArrayList<>();
|
||||
|
||||
@Internal
|
||||
public Map<String, DottedChain> dottedChainCache = new HashMap<>();
|
||||
|
||||
public synchronized int addInt(long value) {
|
||||
|
||||
@@ -692,7 +692,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
|
||||
scope = localData.scopeStack.size();
|
||||
localData.scopeStack.add(new PropertyAVM2Item(null, item.functionName, abc, allABCs, new ArrayList<>(), localData.callStack));
|
||||
}
|
||||
ret.add(ins(AVM2Instructions.NewFunction, method(true, false, localData.callStack, localData.pkg, item.needsActivation, item.subvariables, 0 /*Set later*/, item.hasRest, item.line, localData.currentClass, null, false, localData, item.paramTypes, item.paramNames, item.paramValues, item.body, item.retType)));
|
||||
ret.add(ins(AVM2Instructions.NewFunction, method(abc.constants.getStringId(item.functionName, true), true, false, localData.callStack, localData.pkg, item.needsActivation, item.subvariables, 0 /*Set later*/, item.hasRest, item.line, localData.currentClass, null, false, localData, item.paramTypes, item.paramNames, item.paramValues, item.body, item.retType)));
|
||||
if (!item.functionName.isEmpty()) {
|
||||
ret.add(ins(AVM2Instructions.Dup));
|
||||
ret.add(ins(AVM2Instructions.GetScopeObject, scope));
|
||||
@@ -1178,14 +1178,14 @@ public class AVM2SourceGenerator implements SourceGenerator {
|
||||
generateTraitsPhase3(initScope, isInterface, name, superName, true, localData, traitItems, classInfo.static_traits, st, new HashMap<>(), class_index);
|
||||
int init = 0;
|
||||
if (constructor == null || isInterface) {
|
||||
instanceInfo.iinit_index = init = method(false, isInterface, new ArrayList<>(), pkg, false, new ArrayList<>(), initScope + 1, false, 0, isInterface ? null : name, extendsVal != null ? extendsVal.toString() : null, true, localData, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), TypeItem.UNBOUNDED/*?? FIXME*/);
|
||||
instanceInfo.iinit_index = init = method(0, false, isInterface, new ArrayList<>(), pkg, false, new ArrayList<>(), initScope + 1, false, 0, isInterface ? null : name, extendsVal != null ? extendsVal.toString() : null, true, localData, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), TypeItem.UNBOUNDED/*?? FIXME*/);
|
||||
} else {
|
||||
MethodAVM2Item m = (MethodAVM2Item) constructor;
|
||||
instanceInfo.iinit_index = init = method(false, false, new ArrayList<>(), pkg, m.needsActivation, m.subvariables, initScope + 1, m.hasRest, m.line, name, extendsVal != null ? extendsVal.toString() : null, true, localData, m.paramTypes, m.paramNames, m.paramValues, m.body, TypeItem.UNBOUNDED/*?? FIXME*/);
|
||||
instanceInfo.iinit_index = init = method(0, false, false, new ArrayList<>(), pkg, m.needsActivation, m.subvariables, initScope + 1, m.hasRest, m.line, name, extendsVal != null ? extendsVal.toString() : null, true, localData, m.paramTypes, m.paramNames, m.paramValues, m.body, TypeItem.UNBOUNDED/*?? FIXME*/);
|
||||
}
|
||||
|
||||
//Class initializer
|
||||
int staticMi = method(false, false, new ArrayList<>(), pkg, staticNeedsActivation, sinitVariables, initScope + (implementsStr.isEmpty() ? 0 : 1), false, 0, isInterface ? null : name, superName, false, localData, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), staticInit, TypeItem.UNBOUNDED);
|
||||
int staticMi = method(0, false, false, new ArrayList<>(), pkg, staticNeedsActivation, sinitVariables, initScope + (implementsStr.isEmpty() ? 0 : 1), false, 0, isInterface ? null : name, superName, false, localData, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), staticInit, TypeItem.UNBOUNDED);
|
||||
MethodBody sinitBody = abc.findBody(staticMi);
|
||||
|
||||
List<AVM2Instruction> sinitcode = new ArrayList<>();
|
||||
@@ -1369,7 +1369,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int method(boolean subMethod, boolean isInterface, List<MethodBody> callStack, DottedChain pkg, boolean needsActivation, List<AssignableAVM2Item> subvariables, int initScope, boolean hasRest, int line, String className, String superType, boolean constructor, SourceGeneratorLocalData localData, List<GraphTargetItem> paramTypes, List<String> paramNames, List<GraphTargetItem> paramValues, List<GraphTargetItem> body, GraphTargetItem retType) throws CompilationException {
|
||||
public int method(int name_index, boolean subMethod, boolean isInterface, List<MethodBody> callStack, DottedChain pkg, boolean needsActivation, List<AssignableAVM2Item> subvariables, int initScope, boolean hasRest, int line, String className, String superType, boolean constructor, SourceGeneratorLocalData localData, List<GraphTargetItem> paramTypes, List<String> paramNames, List<GraphTargetItem> paramValues, List<GraphTargetItem> body, GraphTargetItem retType) throws CompilationException {
|
||||
//Reference<Boolean> hasArgs = new Reference<>(Boolean.FALSE);
|
||||
//calcRegisters(localData,needsActivation,paramNames,subvariables,body, hasArgs);
|
||||
SourceGeneratorLocalData newlocalData = new SourceGeneratorLocalData(new HashMap<>(), 1, true, 0);
|
||||
@@ -1611,7 +1611,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
MethodInfo mi = new MethodInfo(param_types, constructor ? 0 : typeName(localData, retType), 0/*name_index*/, 0, optional, new int[0]/*no param_names*/);
|
||||
MethodInfo mi = new MethodInfo(param_types, constructor ? 0 : typeName(localData, retType), name_index, 0, optional, new int[0]/*no param_names*/);
|
||||
if (hasArguments) {
|
||||
mi.setFlagNeed_Arguments();
|
||||
}
|
||||
@@ -1629,7 +1629,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
|
||||
|
||||
int mindex;
|
||||
if (!isInterface) {
|
||||
MethodBody mbody = new MethodBody(abc);
|
||||
MethodBody mbody = new MethodBody(abc, new Traits(), new byte[0], new ABCException[0]);
|
||||
|
||||
if (needsActivation) {
|
||||
int slotId = 1;
|
||||
@@ -1984,10 +1984,10 @@ public class AVM2SourceGenerator implements SourceGenerator {
|
||||
if (mai.isStatic() != generateStatic) {
|
||||
continue;
|
||||
}
|
||||
((TraitMethodGetterSetter) traits[k]).method_info = method(false, isInterface, new ArrayList<>(), mai.pkg, mai.needsActivation, mai.subvariables, methodInitScope + (mai.isStatic() ? 0 : 1), mai.hasRest, mai.line, className, superName, false, localData, mai.paramTypes, mai.paramNames, mai.paramValues, mai.body, mai.retType);
|
||||
((TraitMethodGetterSetter) traits[k]).method_info = method(abc.constants.getStringId(mai.functionName, true), false, isInterface, new ArrayList<>(), mai.pkg, mai.needsActivation, mai.subvariables, methodInitScope + (mai.isStatic() ? 0 : 1), mai.hasRest, mai.line, className, superName, false, localData, mai.paramTypes, mai.paramNames, mai.paramValues, mai.body, mai.retType);
|
||||
} else if (item instanceof FunctionAVM2Item) {
|
||||
FunctionAVM2Item fai = (FunctionAVM2Item) item;
|
||||
((TraitFunction) traits[k]).method_info = method(false, isInterface, new ArrayList<>(), fai.pkg, fai.needsActivation, fai.subvariables, methodInitScope, fai.hasRest, fai.line, className, superName, false, localData, fai.paramTypes, fai.paramNames, fai.paramValues, fai.body, fai.retType);
|
||||
((TraitFunction) traits[k]).method_info = method(abc.constants.getStringId(fai.functionName, true), false, isInterface, new ArrayList<>(), fai.pkg, fai.needsActivation, fai.subvariables, methodInitScope, fai.hasRest, fai.line, className, superName, false, localData, fai.paramTypes, fai.paramNames, fai.paramValues, fai.body, fai.retType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2137,7 +2137,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
|
||||
Trait[] traitArr = generateTraitsPhase1(null, null, true, localData, commands, si.traits, class_index);
|
||||
generateTraitsPhase2(new ArrayList<>(), null/*FIXME*/, commands, traitArr, new ArrayList<>(), localData);
|
||||
MethodInfo mi = new MethodInfo(new int[0], 0, 0, 0, new ValueKind[0], new int[0]);
|
||||
MethodBody mb = new MethodBody(abc);
|
||||
MethodBody mb = new MethodBody(abc, new Traits(), new byte[0], new ABCException[0]);
|
||||
mb.method_info = abc.addMethodInfo(mi);
|
||||
mb.setCode(new AVM2Code());
|
||||
List<AVM2Instruction> mbCode = mb.getCode().code;
|
||||
@@ -2162,21 +2162,23 @@ public class AVM2SourceGenerator implements SourceGenerator {
|
||||
if (abc.instance_info.get(tc.class_info).isInterface()) {
|
||||
mbCode.add(ins(AVM2Instructions.PushNull));
|
||||
} else {
|
||||
|
||||
parentNamesAddNames(abc, allABCs, abc.instance_info.get(tc.class_info).name_index, parents, new ArrayList<>(), new ArrayList<>());
|
||||
parents.remove(0); //remove this class
|
||||
|
||||
//add all parent objects to scopestack
|
||||
for (int i = parents.size() - 1; i >= 0; i--) {
|
||||
mbCode.add(ins(AVM2Instructions.GetLex, parents.get(i)));
|
||||
mbCode.add(ins(AVM2Instructions.PushScope));
|
||||
traitScope++;
|
||||
}
|
||||
//direct parent class to new_class instruction
|
||||
mbCode.add(ins(AVM2Instructions.GetLex, parents.get(0)));
|
||||
}
|
||||
mbCode.add(ins(AVM2Instructions.NewClass, tc.class_info));
|
||||
if (!abc.instance_info.get(tc.class_info).isInterface()) {
|
||||
for (int i = parents.size() - 1; i >= 1; i--) {
|
||||
mbCode.add(ins(AVM2Instructions.PopScope));
|
||||
}
|
||||
for (int i = 0; i < parents.size(); i++) {
|
||||
mbCode.add(ins(AVM2Instructions.PopScope));
|
||||
}
|
||||
|
||||
mbCode.add(ins(AVM2Instructions.InitProperty, tc.name_index));
|
||||
initScopes.put(t, traitScope);
|
||||
traitScope = 1;
|
||||
|
||||
@@ -27,6 +27,12 @@ public class MetadataInfo {
|
||||
|
||||
public int[] values;
|
||||
|
||||
public MetadataInfo() {
|
||||
this.name_index = 0;
|
||||
this.keys = new int[0];
|
||||
this.values = new int[0];
|
||||
}
|
||||
|
||||
public MetadataInfo(int name_index, int[] keys, int[] values) {
|
||||
this.name_index = name_index;
|
||||
this.keys = keys;
|
||||
|
||||
@@ -94,10 +94,14 @@ public final class MethodBody implements Cloneable {
|
||||
@Internal
|
||||
private ABC abc;
|
||||
|
||||
public MethodBody(ABC abc) {
|
||||
public MethodBody() {
|
||||
this.traits = new Traits();
|
||||
this.codeBytes = SWFInputStream.BYTE_ARRAY_EMPTY;
|
||||
this.exceptions = new ABCException[0];
|
||||
this.abc = null;
|
||||
}
|
||||
|
||||
public void setAbc(ABC abc) {
|
||||
this.abc = abc;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.abc.types.ABCException;
|
||||
import com.jpexs.decompiler.flash.abc.types.ClassInfo;
|
||||
import com.jpexs.decompiler.flash.abc.types.Decimal;
|
||||
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
|
||||
import com.jpexs.decompiler.flash.abc.types.MetadataInfo;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
|
||||
import com.jpexs.decompiler.flash.abc.types.Multiname;
|
||||
@@ -102,6 +103,7 @@ import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -156,6 +158,28 @@ public class SwfXmlImporter {
|
||||
return field;
|
||||
}
|
||||
|
||||
private static void setFieldValue(Field field, Object obj, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException {
|
||||
Field modifiersField = Field.class.getDeclaredField("modifiers");
|
||||
modifiersField.setAccessible(true);
|
||||
|
||||
//Remove final attribute temporary (For example Multiname.namespace_set_index
|
||||
int originalModifiers = field.getModifiers();
|
||||
if ((originalModifiers & Modifier.FINAL) > 0) {
|
||||
modifiersField.setInt(field, originalModifiers & ~Modifier.FINAL);
|
||||
}
|
||||
|
||||
field.setAccessible(true);
|
||||
|
||||
int newModifiers = field.getModifiers();
|
||||
|
||||
field.set(obj, value);
|
||||
|
||||
//Put final back in
|
||||
if (originalModifiers != newModifiers) {
|
||||
modifiersField.setInt(field, originalModifiers);
|
||||
}
|
||||
}
|
||||
|
||||
private void processElement(Element element, Object obj, SWF swf, Tag tag) {
|
||||
Class cls = obj.getClass();
|
||||
for (int i = 0; i < element.getAttributes().getLength(); i++) {
|
||||
@@ -165,7 +189,7 @@ public class SwfXmlImporter {
|
||||
try {
|
||||
Field field = getField(cls, name);
|
||||
String attrValue = attr.getValue();
|
||||
field.set(obj, getAs(field.getType(), attrValue));
|
||||
setFieldValue(field, obj, getAs(field.getType(), attrValue));
|
||||
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
|
||||
logger.log(Level.SEVERE, null, ex);
|
||||
}
|
||||
@@ -191,7 +215,7 @@ public class SwfXmlImporter {
|
||||
}
|
||||
}
|
||||
|
||||
field.set(obj, list);
|
||||
setFieldValue(field, obj, list);
|
||||
} else if (childCls.isArray()) {
|
||||
List list = new ArrayList();
|
||||
for (int j = 0; j < child.getChildNodes().getLength(); j++) {
|
||||
@@ -208,10 +232,10 @@ public class SwfXmlImporter {
|
||||
Array.set(array, j, list.get(j));
|
||||
}
|
||||
|
||||
field.set(obj, array);
|
||||
setFieldValue(field, obj, array);
|
||||
} else {
|
||||
Object childObj = processObject(child, null, swf, tag);
|
||||
field.set(obj, childObj);
|
||||
setFieldValue(field, obj, childObj);
|
||||
}
|
||||
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException | NoSuchMethodException | InstantiationException | InvocationTargetException ex) {
|
||||
logger.log(Level.SEVERE, null, ex);
|
||||
@@ -274,7 +298,7 @@ public class SwfXmlImporter {
|
||||
CurvedEdgeRecord.class, EndShapeRecord.class, StraightEdgeRecord.class, StyleChangeRecord.class,
|
||||
BEVELFILTER.class, BLURFILTER.class, COLORMATRIXFILTER.class, CONVOLUTIONFILTER.class,
|
||||
DROPSHADOWFILTER.class, GLOWFILTER.class, GRADIENTBEVELFILTER.class, GRADIENTGLOWFILTER.class,
|
||||
AVM2ConstantPool.class, Decimal.class, Namespace.class, NamespaceSet.class, Multiname.class, MethodInfo.class,
|
||||
AVM2ConstantPool.class, Decimal.class, Namespace.class, NamespaceSet.class, Multiname.class, MethodInfo.class, MetadataInfo.class,
|
||||
ValueKind.class, InstanceInfo.class, Traits.class, TraitClass.class, TraitFunction.class,
|
||||
TraitMethodGetterSetter.class, TraitSlotConst.class, ClassInfo.class, ScriptInfo.class, MethodBody.class,
|
||||
ABCException.class};
|
||||
|
||||
Reference in New Issue
Block a user