From c9dfe10a60765f58d48588c6df0b5e4c7ce3fbbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Fri, 27 Sep 2024 18:29:45 +0200 Subject: [PATCH] Fixed: #2329 AS3 - imports for standalone functions --- CHANGELOG.md | 2 + .../decompiler/flash/abc/ScriptPack.java | 78 ++++++++++++------- .../decompiler/flash/abc/avm2/AVM2Code.java | 9 +++ .../flash/abc/types/traits/Trait.java | 56 ++++++------- .../flash/abc/types/traits/TraitClass.java | 14 +--- .../flash/abc/types/traits/TraitFunction.java | 7 +- .../types/traits/TraitMethodGetterSetter.java | 10 +-- 7 files changed, 93 insertions(+), 83 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64cf846db..8ad6a8ca8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file. - [#2323] AS3 direct editation - Number class traits are duplicated in constructor - [#2324] AS3 direct editation - nested loop continue/break (with labels) - [#2325] AS3 direct editation - allow single quoted attributes in XML +- [#2329] AS3 - imports for standalone functions ## [21.1.0] - 2024-09-23 ### Added @@ -3592,6 +3593,7 @@ Major version of SWF to XML export changed to 2. [#2323]: https://www.free-decompiler.com/flash/issues/2323 [#2324]: https://www.free-decompiler.com/flash/issues/2324 [#2325]: https://www.free-decompiler.com/flash/issues/2325 +[#2329]: https://www.free-decompiler.com/flash/issues/2329 [#943]: https://www.free-decompiler.com/flash/issues/943 [#1812]: https://www.free-decompiler.com/flash/issues/1812 [#2287]: https://www.free-decompiler.com/flash/issues/2287 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java index ebf748ba5..08a2ef7e3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java @@ -35,6 +35,7 @@ import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.abc.types.ScriptInfo; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; +import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; @@ -321,33 +322,41 @@ public class ScriptPack extends AS3ClassTreeItem { } DottedChain pkg = getPathPackage(); - + + List traitList = new ArrayList<>(); + List traitIndicesList = new ArrayList<>(traitIndices); for (int t : traitIndices) { - Trait trait = traits.get(t); + traitList.add(trait); + } + + List fullyQualifiedNames = new ArrayList<>(); - if (trait instanceof TraitSlotConst) { + for (int t = 0; t < traitList.size(); t++) { + + Trait trait = traitList.get(t); + + int nskind = trait.getName(abc).getSimpleNamespaceKind(abc.constants); + if ((nskind != Namespace.KIND_PACKAGE) && (nskind != Namespace.KIND_PACKAGE_INTERNAL)) { continue; } if (!first) { writer.newLine(); } - writer.startTrait(t); - Multiname name = trait.getName(abc); - int nskind = name.getSimpleNamespaceKind(abc.constants); - if ((nskind == Namespace.KIND_PACKAGE) || (nskind == Namespace.KIND_PACKAGE_INTERNAL)) { - trait.toStringPackaged(abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, false); - } else { - trait.toString(abcIndex, pkg, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, false); - } + writer.startTrait(traitIndicesList.get(t)); + trait.toStringPackaged(abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, fullyQualifiedNames, parallel, false); + if (!(trait instanceof TraitClass)) { writer.endTrait(); } first = false; + traitList.remove(t); + traitIndicesList.remove(t); + t--; } - List fullyQualifiedNames = new ArrayList<>(); + if (!first) { writer.newLine(); } @@ -355,22 +364,33 @@ public class ScriptPack extends AS3ClassTreeItem { if (isSimple) { ignorePackage = getPathPackage(); } - List importTraits = new ArrayList<>(); - for (int t : traitIndices) { - Trait trait = traits.get(t); - - if (!(trait instanceof TraitSlotConst)) { - continue; - } - importTraits.add(trait); - } - Trait.writeImports(importTraits, script_init, abcIndex, scriptIndex, -1, true, abc, writer, ignorePackage, fullyQualifiedNames); + Trait.writeImports(traitList, script_init, abcIndex, scriptIndex, -1, true, abc, writer, ignorePackage, fullyQualifiedNames); first = true; - //Slot const last - for (int t : traitIndices) { + for (int t = 0; t < traitList.size(); t++) { + Trait trait = traitList.get(t); + if (trait instanceof TraitSlotConst) { + continue; + } + if (!first) { + writer.newLine(); + } + writer.startTrait(traitIndicesList.get(t)); + trait.toString(abcIndex, pkg, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, false); - Trait trait = traits.get(t); + if (!(trait instanceof TraitClass)) { + writer.endTrait(); + } + first = false; + traitList.remove(t); + traitIndicesList.remove(t); + t--; + } + + //Slot const last + for (int t = 0; t < traitList.size(); t++) { + + Trait trait = traitList.get(t); if (!(trait instanceof TraitSlotConst)) { continue; @@ -383,17 +403,15 @@ public class ScriptPack extends AS3ClassTreeItem { if (!first) { writer.newLine(); } - writer.startTrait(t); + writer.startTrait(traitIndicesList.get(t)); Multiname name = trait.getName(abc); int nskind = name.getSimpleNamespaceKind(abc.constants); if ((nskind == Namespace.KIND_PACKAGE) || (nskind == Namespace.KIND_PACKAGE_INTERNAL)) { trait.toStringPackaged(abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, false); } else { - trait.toString(abcIndex, pkg, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, false); - } - if (!(trait instanceof TraitClass)) { - writer.endTrait(); + trait.toString(abcIndex, pkg, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, false); } + writer.endTrait(); first = false; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 5dce393fe..e4a97e250 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -2706,6 +2706,15 @@ public class AVM2Code implements Cloneable { if (commandToAssigned.containsKey(ti)) { AssignedValue asv = commandToAssigned.get(ti); TraitSlotConst tsc = commandToTrait.get(ti); + + int nsKind = tsc.getName(abc).getSimpleNamespaceKind(abc.constants); + if (classIndex == -1 && (nsKind == Namespace.KIND_PACKAGE || nsKind == Namespace.KIND_PACKAGE_INTERNAL)) { + list.remove(i); + i--; + continue; + } + + TraitSlotConstAVM2Item item = new TraitSlotConstAVM2Item( ti.getSrc(), ti.getLineStartItem(), diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java index 9f076cd7f..03f35487a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java @@ -391,17 +391,16 @@ public abstract class Trait implements Cloneable, Serializable { traitNamesInThisScript.add(st.getName(abc).getName(abc.constants, new ArrayList<>(), true, true)); } } - + Set traitNamesInThisScriptSet = new LinkedHashSet<>(traitNamesInThisScript); traitNamesInThisScript = new ArrayList<>(traitNamesInThisScriptSet); - + //imports List dependencies = new ArrayList<>(); String customNs = null; List uses = new ArrayList<>(); Reference numberContextRef = new Reference<>(null); - - + for (Trait trait : traits) { Multiname multiname = trait.getName(abc); int nskind = multiname.getSimpleNamespaceKind(abc.constants); @@ -419,16 +418,13 @@ public abstract class Trait implements Cloneable, Serializable { imports.add(d.getId()); } } - List importedNames = new ArrayList<>(); - - importedNames.addAll(Arrays.asList(builtInClasses)); + + importedNames.addAll(Arrays.asList(builtInClasses)); importedNames.addAll(namesInThisPackage); importedNames.addAll(traitNamesInThisScript); - - - + for (DottedChain imp : imports) { if (imp.getLast().equals("*")) { if (imp.getWithoutLast().equals(ignorePackage)) { @@ -451,7 +447,7 @@ public abstract class Trait implements Cloneable, Serializable { i--; } } - + for (int i = 0; i < imports.size(); i++) { DottedChain ipath = imports.get(i); DottedChain pkg = ipath.getWithoutLast(); @@ -465,9 +461,9 @@ public abstract class Trait implements Cloneable, Serializable { for (int i = 0; i < imports.size(); i++) { DottedChain ipath = imports.get(i); String name = ipath.getLast(); - importedNames.add(name); + importedNames.add(name); } - + List uniqueImportedNames = new ArrayList<>(); for (int i = 0; i < importedNames.size(); i++) { String name = importedNames.get(i); @@ -497,7 +493,6 @@ public abstract class Trait implements Cloneable, Serializable { hasImport = true; } } - boolean hasUse = false; if (!uses.isEmpty()) { @@ -653,24 +648,28 @@ public abstract class Trait implements Cloneable, Serializable { } Set namespaceIdsClass = new HashSet<>(); - Multiname mc = abc.instance_info.get(classIndex).getName(abc.constants); - if (mc.isApiVersioned(abc.constants)) { - NamespaceSet nss = mc.getNamespaceSet(abc.constants); - for (int n : nss.namespaces) { - namespaceIdsClass.add(n); - } + if (classIndex == -1) { + nskind = Namespace.KIND_PACKAGE_INTERNAL; } else { - namespaceIdsClass.add(mc.namespace_index); - } + Multiname mc = abc.instance_info.get(classIndex).getName(abc.constants); + if (mc.isApiVersioned(abc.constants)) { + NamespaceSet nss = mc.getNamespaceSet(abc.constants); + for (int n : nss.namespaces) { + namespaceIdsClass.add(n); + } + } else { + namespaceIdsClass.add(mc.namespace_index); + } - for (int ns : namespaceIdsThis) { - if (namespaceIdsClass.contains(ns)) { - nskind = Namespace.KIND_PACKAGE_INTERNAL; - break; + for (int ns : namespaceIdsThis) { + if (namespaceIdsClass.contains(ns)) { + nskind = Namespace.KIND_PACKAGE_INTERNAL; + break; + } } } } - + if (!(classIndex == -1 && nskind == Namespace.KIND_PACKAGE_INTERNAL)) { String nsPrefix = Namespace.getPrefix(nskind); if (nsPrefix != null && !nsPrefix.isEmpty()) { @@ -876,6 +875,9 @@ public abstract class Trait implements Cloneable, Serializable { writer.appendNoHilight(" " + nsname); //assume not null name } writer.startBlock(); + List traits = new ArrayList<>(); + traits.add(this); + writeImports(traits, -1, abcIndex, scriptIndex, classIndex, isStatic, abc, writer, getPackage(abc), fullyQualifiedNames); toString(abcIndex, name.getNameWithNamespace(abc.constants, true).getWithoutLast(), parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, insideInterface); writer.endBlock(); writer.newLine(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index e03773dde..0ef514dc7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -211,17 +211,9 @@ public class TraitClass extends Trait implements TraitWithSlot { Multiname instanceInfoMultiname = instanceInfo.getName(abc.constants); //DottedChain packageName = instanceInfoMultiname.getNamespace(abc.constants).getName(abc.constants); //assume not null name - - fullyQualifiedNames = new ArrayList<>(); - - Reference first = new Reference<>(true); - - if (getName(abc).getNamespace(abc.constants).kind != Namespace.KIND_PACKAGE_INTERNAL) { - List traits = new ArrayList<>(); - traits.add(this); - first.setVal(!writeImports(traits, -1, abcIndex, scriptIndex, classIndex, false, abc, writer, packageName, fullyQualifiedNames)); - } - + + Reference first = new Reference<>(true); + String instanceInfoName = instanceInfoMultiname.getName(abc.constants, fullyQualifiedNames, false, true); getMetaData(this, convertData, abc, writer); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java index 4fcdf9b20..d82b6e6f2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; import com.jpexs.decompiler.flash.abc.types.ConvertData; import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.exporters.script.Dependency; import com.jpexs.decompiler.flash.exporters.script.DependencyParser; @@ -125,9 +126,6 @@ public class TraitFunction extends Trait implements TraitWithSlot { @Override public GraphTextWriter toString(AbcIndexing abcIndex, DottedChain packageName, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { - List traits = new ArrayList<>(); - traits.add(this); - writeImports(traits, -1, abcIndex, scriptIndex, classIndex, false, abc, writer, getPackage(abc), fullyQualifiedNames); getMetaData(this, convertData, abc, writer); writer.startMethod(method_info, getName(abc).getName(abc.constants, new ArrayList<>(), true, false)); toStringHeader(parent, packageName, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, insideInterface); @@ -168,9 +166,6 @@ public class TraitFunction extends Trait implements TraitWithSlot { @Override public void convert(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { fullyQualifiedNames = new ArrayList<>(); - List traits = new ArrayList<>(); - traits.add(this); - writeImports(traits, -1, abcIndex, scriptIndex, classIndex, false, abc, writer, getPackage(abc), fullyQualifiedNames); writer.startMethod(method_info, getName(abc).getName(abc.constants, new ArrayList<>(), true, false)); convertHeader(parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); int bodyIndex = abc.findBodyIndex(method_info); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java index ef630e7b7..9836c06f8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java @@ -167,11 +167,7 @@ public class TraitMethodGetterSetter extends Trait { */ @Override public void convert(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { - if (classIndex < 0) { - List traits = new ArrayList<>(); - traits.add(this); - writeImports(traits, -1, abcIndex, scriptIndex, classIndex, isStatic, abc, writer, getPackage(abc), fullyQualifiedNames); - } + int nsKind = getName(abc).getSimpleNamespaceKind(abc.constants); writer.startMethod(method_info, getName(abc).getName(abc.constants, new ArrayList<>(), true, false)); path = path + "." + getName(abc).getName(abc.constants, fullyQualifiedNames, false, true); convertHeader(parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); @@ -202,10 +198,6 @@ public class TraitMethodGetterSetter extends Trait { @Override public GraphTextWriter toString(AbcIndexing abcIndex, DottedChain packageName, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { - - if (classIndex < 0) { - //writeImports(this, -1, abcIndex, scriptIndex, classIndex, isStatic, abc, writer, getPackage(abc), fullyQualifiedNames); - } getMetaData(this, convertData, abc, writer); writer.startMethod(method_info, getName(abc).getName(abc.constants, new ArrayList<>(), true, false)); path = path + "." + getName(abc).getName(abc.constants, fullyQualifiedNames, false, true);