/* * Copyright (C) 2010-2016 JPEXS, All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. */ 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.AVM2ConstantPool; 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.instructions.other.FindPropertyStrictIns; import com.jpexs.decompiler.flash.abc.avm2.model.ApplyTypeAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.InitVectorAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.Multiname; 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.TraitSlotConst; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphSourceItem; 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 java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author JPEXS */ public class PropertyAVM2Item extends AssignableAVM2Item { public String propertyName; public GraphTargetItem object; public AbcIndexing abcIndex; private final List<NamespaceItem> openedNamespaces; private final List<MethodBody> callStack; public List<GraphTargetItem> scopeStack = new ArrayList<>(); @Override public AssignableAVM2Item copy() { PropertyAVM2Item p = new PropertyAVM2Item(object, propertyName, abcIndex, openedNamespaces, callStack); return p; } public PropertyAVM2Item(GraphTargetItem object, String propertyName, AbcIndexing abcIndex, List<NamespaceItem> openedNamespaces, List<MethodBody> callStack) { this.propertyName = propertyName; this.object = object; this.abcIndex = abcIndex; this.openedNamespaces = openedNamespaces; this.callStack = callStack; } @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { return writer; } private int allNsSet(AbcIndexing abc) throws CompilationException { int[] nssa = new int[openedNamespaces.size()]; for (int i = 0; i < nssa.length; i++) { nssa[i] = openedNamespaces.get(i).getCpoolIndex(abc); } return abc.getSelectedAbc().constants.getNamespaceSetId(nssa, true); } private static GraphTargetItem multinameToType(Set<Integer> visited, int m_index, AVM2ConstantPool constants) { if (visited.contains(m_index)) { Logger.getLogger(PropertyAVM2Item.class.getName()).log(Level.WARNING, "Recursive typename detected"); return null; } if (m_index == 0) { return TypeItem.UNBOUNDED; } Multiname m = constants.getMultiname(m_index); if (m.kind == Multiname.TYPENAME) { visited.add(m_index); GraphTargetItem obj = multinameToType(visited, m.qname_index, constants); if (obj == null) { return null; } List<GraphTargetItem> params = new ArrayList<>(); for (int pm : m.params) { GraphTargetItem r = multinameToType(visited, pm, constants); if (r == null) { return null; } if (pm == 0) { r = new NullAVM2Item(null, null); } params.add(r); } return new ApplyTypeAVM2Item(null, null, obj, params); } else { return new TypeItem(m.getNameWithNamespace(constants, true)); } } public static GraphTargetItem multinameToType(int m_index, AVM2ConstantPool constants) { return multinameToType(new HashSet<>(), m_index, constants); } public void resolve(boolean mustExist, SourceGeneratorLocalData localData, Reference<GraphTargetItem> objectType, Reference<GraphTargetItem> propertyType, Reference<Integer> propertyIndex, Reference<ValueKind> propertyValue, Reference<ABC> propertyValueABC) throws CompilationException { GraphTargetItem thisType = new TypeItem(localData.getFullClass()); GraphTargetItem objType = null; GraphTargetItem objSubType = null; ValueKind propValue = null; ABC propValueAbc = null; if (object != null) { GraphTargetItem oretType = object.returnType(); if (oretType instanceof UnresolvedAVM2Item) { UnresolvedAVM2Item ur = (UnresolvedAVM2Item) oretType; oretType = ur.resolved; } if (oretType instanceof ApplyTypeAVM2Item) { ApplyTypeAVM2Item t = (ApplyTypeAVM2Item) oretType; objType = t; } else if (oretType instanceof TypeItem) { TypeItem t = (TypeItem) oretType; objType = t; } else { objType = new TypeItem(oretType.toString()); } } GraphTargetItem propType = null; int propIndex = 0; ABC abc = abcIndex.getSelectedAbc(); AVM2ConstantPool constants = abc.constants; if (!propertyName.startsWith("@")) { if (scopeStack.isEmpty()) { //Everything is multiname when with command if (objType == null) { /*for (GraphTargetItem s : scopeStack) { String oType = s.returnType().toString(); String name = oType; String nsname = ""; if(name.contains(".")){ nsname = name.substring(0,name.lastIndexOf(".")); name = name.substring(name.lastIndexOf(".")+1); } List<ABC> abcs = new ArrayList<>(); abcs.add(abc); abcs.addAll(otherABCs); loopabc: for (ABC a : abcs) { for (int h = 0; h < a.instance_info.size(); h++) { InstanceInfo ii = a.instance_info.get(h); Multiname n = a.constants.constant_multiname.get(ii.name_index); if (name.equals(n.getName(a.constants, new ArrayList<>())) && n.getNamespace(a.constants).hasName(nsname,a.constants)) { Reference<String> outName = new Reference<>(""); Reference<String> outNs = new Reference<>(""); Reference<String> outPropNs = new Reference<>(""); Reference<Integer> outPropNsKind = new Reference<>(1); Reference<String> outPropType = new Reference<>(""); if (AVM2SourceGenerator.searchPrototypeChain(false, abcs, nsname, name, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropType)) { objType = "".equals(outNs.getVal()) ? outName.getVal() : outNs.getVal() + "." + outName.getVal(); propType = outPropType.getVal(); propIndex = abc.constants.getMultinameId(new Multiname(Multiname.QNAME, abc.constants.getStringId(propertyName, true), abc.constants.getNamespaceId(new Namespace(outPropNsKind.getVal(), abc.constants.getStringId(outPropNs.getVal(), true)), 0, true), 0, 0, new ArrayList<Integer>()), true ); break loopabc; } } } } }*/ } GraphTargetItem ttype = objType; if (ttype == null) { ttype = thisType; } { if (ttype.equals(new TypeItem(InitVectorAVM2Item.VECTOR_FQN))) { switch ("" + objSubType) { case "int": ttype = new TypeItem(InitVectorAVM2Item.VECTOR_INT); break; case "Number": ttype = new TypeItem(InitVectorAVM2Item.VECTOR_DOUBLE); break; case "uint": ttype = new TypeItem(InitVectorAVM2Item.VECTOR_UINT); break; default: ttype = new TypeItem(InitVectorAVM2Item.VECTOR_OBJECT); } } /* AbcIndexing.TraitIndex p = abc.findProperty(new AbcIndexing.PropertyDef(propertyName, ttype), false, true); if(p!=null){ objType = new TypeItem(outNs.getVal().isEmpty() ? outName.getVal() : outNs.getVal().toRawString() + "." + outName.getVal()); propType = p.type; propIndex = abc.getLastAbc().constants.getMultinameId(new Multiname(Multiname.QNAME, abc.getLastAbc().getStringId(propertyName, true), abc.getLastAbc().getNamespaceId(new Namespace(outPropNsKind.getVal(), abc.constants.getStringId(outPropNs.getVal(), true)), outPropNsIndex.getVal(), true), 0, 0, new ArrayList<>()), true ); propValue = outPropValue.getVal(); }*/ if (ttype instanceof TypeItem) { DottedChain ftn = ((TypeItem) ttype).fullTypeName; Reference<String> outName = new Reference<>(""); Reference<DottedChain> outNs = new Reference<>(DottedChain.EMPTY); Reference<DottedChain> outPropNs = new Reference<>(DottedChain.EMPTY); Reference<Integer> outPropNsKind = new Reference<>(1); Reference<Integer> outPropNsIndex = new Reference<>(0); Reference<GraphTargetItem> outPropType = new Reference<>(null); Reference<ValueKind> outPropValue = new Reference<>(null); Reference<ABC> outPropValueAbc = new Reference<>(null); List<Integer> otherNs = new ArrayList<>(); for (NamespaceItem n : openedNamespaces) { if (n.isResolved()) { otherNs.add(n.getCpoolIndex(abcIndex)); } } if (AVM2SourceGenerator.searchPrototypeChain(otherNs, localData.privateNs, localData.protectedNs, false, abcIndex, ftn.getWithoutLast(), ftn.getLast(), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc)) { objType = new TypeItem(outNs.getVal().addWithSuffix(outName.getVal())); propType = outPropType.getVal(); propIndex = constants.getMultinameId(Multiname.createQName(false, constants.getStringId(propertyName, true), constants.getNamespaceId(outPropNsKind.getVal(), outPropNs.getVal(), outPropNsIndex.getVal(), true)), true ); propValue = outPropValue.getVal(); propValueAbc = outPropValueAbc.getVal(); } } if (objType == null) { for (MethodBody b : callStack) { for (int i = 0; i < b.traits.traits.size(); i++) { Trait t = b.traits.traits.get(i); if (t.getName(abc).getName(constants, null, true, true).equals(propertyName)) { if (t instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst) t; objType = new TypeItem(DottedChain.FUNCTION); propType = multinameToType(tsc.type_index, constants); propIndex = tsc.name_index; if (!localData.traitUsages.containsKey(b)) { localData.traitUsages.put(b, new ArrayList<>()); } localData.traitUsages.get(b).add(i); } } } } if (objType == null) { loopobjType: for (int i = 0; i < openedNamespaces.size(); i++) { if (!openedNamespaces.get(i).isResolved()) { continue; } int nsindex = openedNamespaces.get(i).getCpoolIndex(abcIndex); int nsKind = openedNamespaces.get(i).kind; DottedChain nsname = openedNamespaces.get(i).name; int name_index = 0; for (int m = 1; m < constants.getMultinameCount(); m++) { Multiname mname = constants.getMultiname(m); if (mname.kind == Multiname.QNAME && mname.getName(constants, null, true, true).equals(propertyName) && mname.namespace_index == nsindex) { name_index = m; break; } } if (name_index > 0) { for (int c = 0; c < abc.instance_info.size(); c++) { if (abc.instance_info.get(c).deleted) { continue; } for (Trait t : abc.instance_info.get(c).instance_traits.traits) { if (t.name_index == name_index) { objType = multinameToType(abc.instance_info.get(c).name_index, constants); propType = AVM2SourceGenerator.getTraitReturnType(abcIndex, t); propIndex = t.name_index; if (t instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst) t; propValue = new ValueKind(tsc.value_index, tsc.value_kind); propValueAbc = abc; } break loopobjType; } } for (Trait t : abc.class_info.get(c).static_traits.traits) { if (t.name_index == name_index) { objType = multinameToType(abc.instance_info.get(c).name_index, constants); propType = AVM2SourceGenerator.getTraitReturnType(abcIndex, t); propIndex = t.name_index; if (t instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst) t; propValue = new ValueKind(tsc.value_index, tsc.value_kind); propValueAbc = abc; } break loopobjType; } } } for (ScriptInfo si : abc.script_info) { if (si.deleted) { continue; } for (Trait t : si.traits.traits) { if (t.name_index == name_index) { objType = new TypeItem(DottedChain.OBJECT); propType = AVM2SourceGenerator.getTraitReturnType(abcIndex, t); propIndex = t.name_index; if (t instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst) t; propValue = new ValueKind(tsc.value_index, tsc.value_kind); propValueAbc = abc; } break loopobjType; } } } } if (nsKind == Namespace.KIND_PACKAGE && propertyName != null) { AbcIndexing.TraitIndex p = abcIndex.findNsProperty(new AbcIndexing.PropertyNsDef(propertyName, nsname, abc, openedNamespaces.get(i).getCpoolIndex(abcIndex)), true, true); Reference<String> outName = new Reference<>(""); Reference<DottedChain> outNs = new Reference<>(DottedChain.EMPTY); Reference<DottedChain> outPropNs = new Reference<>(DottedChain.EMPTY); Reference<Integer> outPropNsKind = new Reference<>(1); Reference<Integer> outPropNsIndex = new Reference<>(0); Reference<GraphTargetItem> outPropType = new Reference<>(null); Reference<ValueKind> outPropValue = new Reference<>(null); Reference<ABC> outPropValueAbc = new Reference<>(null); if (p != null && (p.objType instanceof TypeItem)) { List<Integer> otherns = new ArrayList<>(); for (NamespaceItem n : openedNamespaces) { if (n.isResolved()) { 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)) { objType = new TypeItem(outNs.getVal().addWithSuffix(outName.getVal())); propType = p.returnType; propIndex = constants.getMultinameId(Multiname.createQName(false, constants.getStringId(propertyName, true), constants.getNamespaceId(outPropNsKind.getVal(), outPropNs.getVal(), outPropNsIndex.getVal(), true)), true ); propValue = p.value; propValueAbc = outPropValueAbc.getVal(); break loopobjType; } } //if (propertyName != null && AVM2SourceGenerator.searchPrototypeChain(false, abcs, nsname, n.getName(a.constants, null, true), propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue)) { // //} } } } } } } } if (propIndex == 0 && !mustExist) { String pname = propertyName; boolean attr = pname.startsWith("@"); if (attr) { pname = pname.substring(1); } Multiname multiname; if (attr && pname.isEmpty()) { multiname = Multiname.createMultinameL(true, constants.getNamespaceSetId(new int[]{constants.getNamespaceId(Namespace.KIND_PACKAGE_INTERNAL, localData.pkg, 0, true)}, true)); } else { int name_index = constants.getStringId("*".equals(pname) ? null : pname, true); //Note: name = * is for .@* attribute multiname = Multiname.createMultiname(attr, name_index, allNsSet(abcIndex)); } propIndex = constants.getMultinameId(multiname, true); propType = TypeItem.UNBOUNDED; objType = TypeItem.UNBOUNDED; propValue = null; propValueAbc = null; } propertyValue.setVal(propValue); propertyValueABC.setVal(propValueAbc); propertyIndex.setVal(propIndex); propertyType.setVal(propType); objectType.setVal(objType); } public int resolveProperty(SourceGeneratorLocalData localData) throws CompilationException { Reference<GraphTargetItem> objType = new Reference<>(null); Reference<GraphTargetItem> propType = new Reference<>(null); Reference<Integer> propIndex = new Reference<>(0); Reference<ValueKind> outPropValue = new Reference<>(null); Reference<ABC> outPropValueAbc = new Reference<>(null); resolve(false, localData, objType, propType, propIndex, outPropValue, outPropValueAbc); return propIndex.getVal(); } /* private String resolveObjectType() { String objType = object == null ? null : object.returnType().toString(); if (objType == null) { loopo: for (int i = 0; i < openedNamespaces.size(); i++) { int nsindex = openedNamespaces.get(i); int nsKind = abc.constants.constant_namespace.get(openedNamespaces.get(i)).kind; String nsname = abc.constants.constant_namespace.get(openedNamespaces.get(i)).getName(abc.constants); int name_index = 0; for (int m = 1; m < abc.constants.constant_multiname.size(); m++) { Multiname mname = abc.constants.constant_multiname.get(m); if (mname.kind == Multiname.QNAME && mname.getName(abc.constants, new ArrayList<>()).equals(propertyName) && mname.namespace_index == nsindex) { name_index = m; break; } } if (name_index > 0) { for (int s = 0; s < abc.script_info.size(); s++) { for (Trait t : abc.script_info.get(s).traits.traits) { if (t.name_index == name_index) { return getTraitReturnType(abc, t).toString(); } } } for (int c = 0; c < abc.instance_info.size(); c++) { for (Trait t : abc.instance_info.get(c).instance_traits.traits) { if (t.name_index == name_index) { return getTraitReturnType(abc, t).toString(); } } for (Trait t : abc.class_info.get(c).static_traits.traits) { if (t.name_index == name_index) { return getTraitReturnType(abc, t).toString(); } } } } if (nsKind == Namespace.KIND_PACKAGE) { List<ABC> abcs = new ArrayList<>(); abcs.add(abc); abcs.addAll(otherABCs); loopabc: for (ABC a : otherABCs) { for (int h = 0; h < a.instance_info.size(); h++) { InstanceInfo ii = a.instance_info.get(h); Multiname n = a.constants.constant_multiname.get(ii.name_index); if (n.getNamespace(a.constants).kind == Namespace.KIND_PACKAGE && n.getNamespace(a.constants).getName(a.constants).equals(nsname)) { Reference<String> outName = new Reference<>(""); Reference<String> outNs = new Reference<>(""); Reference<String> outPropNs = new Reference<>(""); Reference<Integer> outPropNsKind = new Reference<>(1); if (AVM2SourceGenerator.searchPrototypeChain(abcs, nsname, n.getName(a.constants, new ArrayList<>()), propertyName, outName, outNs, outPropNs, outPropNsKind)) { return "".equals(outNs.getVal()) ? outName.getVal() : outNs.getVal() + "." + outName.getVal(); } } } } } } } if (objType == null) { throw new RuntimeException("Unresolved object type"); } return objType; }*/ /* public GraphTargetItem resolvePropertyType() { if (index != null) { return TypeItem.UNBOUNDED; } String objType = resolveObjectType(); for (ABC a : abcs) { int ci = a.findClassByName(objType); if (ci != -1) { for (Trait t : a.instance_info.get(ci).instance_traits.traits) { String tnames = t.getName(a).getName(a.constants, new ArrayList<>()); if (tnames.equals(propertyName)) { if (t instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst) t; if (tsc.type_index == 0) { return TypeItem.UNBOUNDED; } return new TypeItem(a.constants.constant_multiname.get(tsc.type_index).getNameWithNamespace(a.constants)); } if (t instanceof TraitMethodGetterSetter) { TraitMethodGetterSetter tmgs = (TraitMethodGetterSetter) t; if (tmgs.kindType == Trait.TRAIT_GETTER) { return new TypeItem(a.constants.constant_multiname.get(a.method_info.get(tmgs.method_info).ret_type).getNameWithNamespace(a.constants)); } if (tmgs.kindType == Trait.TRAIT_SETTER) { return new TypeItem(a.constants.constant_multiname.get(a.method_info.get(tmgs.method_info).param_types[0]).getNameWithNamespace(a.constants)); } } if (t instanceof TraitFunction) { return new TypeItem("Function"); } return TypeItem.UNBOUNDED; } } break; } } return TypeItem.UNBOUNDED; } */ /* public int resolveProperty() { if (index != null) { return abc.constants.getMultinameId(new Multiname(Multiname.MULTINAMEL, abc.constants.getStringId(propertyName, true), 0, allNsSet(), 0, new ArrayList<Integer>()), true); } String objType = resolveObjectType(); for (ABC a : abcs) { int ci = a.findClassByName(objType); if (ci != -1) { for (Trait t : a.instance_info.get(ci).instance_traits.traits) { Multiname tname = t.getName(a); String tnames = t.getName(a).getName(a.constants, new ArrayList<>()); if (tnames.equals(propertyName)) { return abc.constants.getMultinameId(new Multiname(tname.kind, abc.constants.getStringId(tnames, true), abc.constants.getNamespaceId(new Namespace(tname.getNamespace(a.constants).kind, abc.constants.getStringId(tname.getNamespace(a.constants).getName(a.constants), true)), 0, true), 0, 0, new ArrayList<Integer>()), true); } } for (Trait t : a.class_info.get(ci).static_traits.traits) { Multiname tname = t.getName(a); String tnames = t.getName(a).getName(a.constants, new ArrayList<>()); if (tnames.equals(propertyName)) { return abc.constants.getMultinameId(new Multiname(tname.kind, abc.constants.getStringId(tnames, true), abc.constants.getNamespaceId(new Namespace(tname.getNamespace(a.constants).kind, abc.constants.getStringId(tname.getNamespace(a.constants).getName(a.constants), true)), 0, true), 0, 0, new ArrayList<Integer>()), true); } } break; } } for (ABC a : abcs) { for (ScriptInfo si : a.script_info) { for (Trait t : si.traits.traits) { Multiname tname = t.getName(a); String tnames = t.getName(a).getName(a.constants, new ArrayList<>()); if (tnames.equals(propertyName)) { return abc.constants.getMultinameId(new Multiname(tname.kind, abc.constants.getStringId(tnames, true), abc.constants.getNamespaceId(new Namespace(tname.getNamespace(a.constants).kind, abc.constants.getStringId(tname.getNamespace(a.constants).getName(a.constants), true)), 0, true), 0, 0, new ArrayList<Integer>()), true); } } } } return abc.constants.getMultinameId(new Multiname(Multiname.MULTINAME, abc.constants.getStringId(propertyName, true), 0, allNsSet(), 0, new ArrayList<Integer>()), true); }*/ @Override public GraphTargetItem returnType() { Reference<GraphTargetItem> objType = new Reference<>(null); Reference<GraphTargetItem> propType = new Reference<>(null); Reference<Integer> propIndex = new Reference<>(0); Reference<ValueKind> outPropValue = new Reference<>(null); Reference<ABC> outPropValueAbc = new Reference<>(null); try { resolve(false, new SourceGeneratorLocalData(new HashMap<>(), 0, false, 0)/*???*/, objType, propType, propIndex, outPropValue, outPropValueAbc); return propType.getVal(); } catch (CompilationException ex) { Logger.getLogger(PropertyAVM2Item.class.getName()).log(Level.SEVERE, null, ex); } return null; } public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator, boolean needsReturn) throws CompilationException { Reference<GraphTargetItem> objType = new Reference<>(null); Reference<GraphTargetItem> propType = new Reference<>(null); Reference<Integer> propIndex = new Reference<>(0); Reference<ValueKind> outPropValue = new Reference<>(null); Reference<ABC> outPropValueAbc = new Reference<>(null); resolve(false, localData, objType, propType, propIndex, outPropValue, outPropValueAbc); int propertyId = propIndex.getVal(); Object obj = resolveObject(localData, generator); Reference<Integer> ret_temp = new Reference<>(-1); if (assignedValue != null) { GraphTargetItem targetType = propType.getVal(); String srcType = assignedValue.returnType().toString(); GraphTargetItem coerced = assignedValue; if (!targetType.toString().equals(srcType) && !propertyName.startsWith("@")) { coerced = makeCoerced(assignedValue, targetType); } return toSourceMerge(localData, generator, obj, coerced, needsReturn ? dupSetTemp(localData, generator, ret_temp) : null, ins(AVM2Instructions.SetProperty, propertyId), needsReturn ? getTemp(localData, generator, ret_temp) : null, killTemp(localData, generator, Arrays.asList(ret_temp))); } else { if (obj instanceof AVM2Instruction && (((AVM2Instruction) obj).definition instanceof FindPropertyStrictIns)) { return toSourceMerge(localData, generator, ins(AVM2Instructions.GetLex, propertyId), needsReturn ? null : ins(AVM2Instructions.Pop) ); } return toSourceMerge(localData, generator, obj, ins(AVM2Instructions.GetProperty, propertyId), needsReturn ? null : ins(AVM2Instructions.Pop) ); } } @Override public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { return toSource(localData, generator, true); } @Override public List<GraphSourceItem> toSourceIgnoreReturnValue(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { return toSource(localData, generator, false); } @Override public String toString() { return "" + object + "." + propertyName; } @Override public boolean hasReturnValue() { return true; } public Object resolveObject(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { Object obj = object; if (obj == null) { String cname = localData.currentClass; DottedChain pkgName = localData.pkg; Reference<String> outName = new Reference<>(""); Reference<DottedChain> outNs = new Reference<>(DottedChain.EMPTY); Reference<DottedChain> outPropNs = new Reference<>(DottedChain.EMPTY); Reference<Integer> outPropNsKind = new Reference<>(1); Reference<Integer> outPropNsIndex = new Reference<>(0); Reference<GraphTargetItem> outPropType = new Reference<>(null); Reference<ValueKind> outPropValue = new Reference<>(null); Reference<ABC> outPropValueAbc = new Reference<>(null); /*List<ABC> abcs = new ArrayList<>(); abcs.add(abc); abcs.addAll(otherABCs);*/ List<Integer> otherNs = new ArrayList<>(); for (NamespaceItem n : openedNamespaces) { if (n.isResolved()) { 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()))) { NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), 0, "this", null, false, openedNamespaces); nobj.setRegNumber(0); obj = nobj; } else { Reference<GraphTargetItem> objType = new Reference<>(null); Reference<GraphTargetItem> propType = new Reference<>(null); Reference<Integer> propIndex = new Reference<>(0); Reference<ValueKind> propValue = new Reference<>(null); Reference<ABC> propValueAbc = new Reference<>(null); resolve(false, localData, objType, propType, propIndex, outPropValue, propValueAbc); obj = ins(AVM2Instructions.FindPropertyStrict, propIndex.getVal()); } } return obj; } @Override public List<GraphSourceItem> toSourceChange(SourceGeneratorLocalData localData, SourceGenerator generator, boolean post, boolean decrement, boolean needsReturn) throws CompilationException { Reference<GraphTargetItem> objType = new Reference<>(null); Reference<GraphTargetItem> propType = new Reference<>(null); Reference<Integer> propIndex = new Reference<>(0); Reference<ValueKind> outPropValue = new Reference<>(null); Reference<ABC> outPropValueAbc = new Reference<>(null); resolve(false, localData, objType, propType, propIndex, outPropValue, outPropValueAbc); int propertyId = propIndex.getVal(); Object obj = resolveObject(localData, generator); Reference<Integer> ret_temp = new Reference<>(-1); Reference<Integer> obj_temp = new Reference<>(-1); boolean isInteger = propType.getVal().toString().equals("int"); List<GraphSourceItem> ret = toSourceMerge(localData, generator, obj, dupSetTemp(localData, generator, obj_temp), //Start get original //getTemp(localData, generator, obj_temp), //index!=null?getTemp(localData, generator, index_temp):null, ins(AVM2Instructions.GetProperty, propertyId), (!isInteger && post) ? ins(AVM2Instructions.ConvertD) : null, //End get original (!post) ? (decrement ? ins(isInteger ? AVM2Instructions.DecrementI : AVM2Instructions.Decrement) : ins(isInteger ? AVM2Instructions.IncrementI : AVM2Instructions.Increment)) : null, needsReturn ? ins(AVM2Instructions.Dup) : null, (post) ? (decrement ? ins(isInteger ? AVM2Instructions.DecrementI : AVM2Instructions.Decrement) : ins(isInteger ? AVM2Instructions.IncrementI : AVM2Instructions.Increment)) : null, setTemp(localData, generator, ret_temp), getTemp(localData, generator, obj_temp), getTemp(localData, generator, ret_temp), ins(AVM2Instructions.SetProperty, propertyId), //needsReturn?getTemp(localData, generator, ret_temp):null, killTemp(localData, generator, Arrays.asList(ret_temp, obj_temp))); return ret; } }