Fixed: AS3 slow decompilation caused by ambiguios namespace detection

This commit is contained in:
Jindra Petřík
2026-02-23 09:21:44 +01:00
parent 87f94768a0
commit ba7c762537
3 changed files with 66 additions and 79 deletions

View File

@@ -231,8 +231,9 @@ public class FullMultinameAVM2Item extends AVM2Item {
String identifier = IdentifiersDeobfuscation.printIdentifier(localData.abc.getSwf(), localData.usedDeobfuscations, true, nsname);
writer.hilightSpecial(identifier, HighlightSpecialType.TYPE_NAME, customNs.toRawString());
writer.appendNoHilight("::");
} else {
if (parentType instanceof TypeItem) { //not ApplyTypeAVM2Item or UnboundedTypeItem
} else {
//FIXME!! This is slow, should be moved to indexing
if (false && parentType instanceof TypeItem) { //not ApplyTypeAVM2Item or UnboundedTypeItem
String rawName = constants.getMultiname(multinameIndex).getName(localData.usedDeobfuscations, localData.abc, localData.abc.constants, fullyQualifiedNames, true, true);
List<AbcIndexing.PropertyDef> defs = new ArrayList<>();
List<Boolean> staticRef = new ArrayList<>();

View File

@@ -133,84 +133,69 @@ public class ActionScript3ClassTest extends ActionScript3DecompileTestBase {
public void testMyPackage1TestClass2() {
decompileScriptPack("standard", "tests_classes.mypackage1.TestClass2", "package tests_classes.mypackage1\n"
+ "{\n"
+ " import tests_classes.mypackage2.TestClass;\n"
+ " import tests_classes.mypackage3.TestClass;\n"
+ " \n"
+ " use namespace myNamespace;\n"
+ " \n"
+ " public class TestClass2\n"
+ " {\n"
+ " \n"
+ " public function TestClass2()\n"
+ " {\n"
+ " super();\n"
+ " }\n"
+ " \n"
+ " myNamespace static function testCall5() : String\n"
+ " {\n"
+ " return \"x\";\n"
+ " }\n"
+ " \n"
+ " protected static function testCall5() : String\n"
+ " {\n"
+ " return \"5\";\n"
+ " }\n"
+ " \n"
+ " public function testCall() : String\n"
+ " {\n"
+ " var a:tests_classes.mypackage1.TestClass = null;\n"
+ " var b:tests_classes.mypackage2.TestClass = null;\n"
+ " var c:tests_classes.mypackage3.TestClass = null;\n"
+ " a = new tests_classes.mypackage1.TestClass();\n"
+ " b = new tests_classes.mypackage2.TestClass();\n"
+ " c = new tests_classes.mypackage3.TestClass();\n"
+ " var res:String = a.testCall() + b.testCall() + c.testCall() + this.public::testCall2() + this.private::testCall3() + this.protected::testCall4() + protected::testCall5() + this.internal::testCall6() + myNamespace::testCall3();\n"
+ " trace(res);\n"
+ " return res;\n"
+ " }\n"
+ " \n"
+ " myNamespace function testCall2() : String\n"
+ " {\n"
+ " return \"1\";\n"
+ " }\n"
+ " \n"
+ " myNamespace function testCall3() : String\n"
+ " {\n"
+ " return myNamespace::testCall2();\n"
+ " }\n"
+ " \n"
+ " myNamespace function testCall4() : String\n"
+ " {\n"
+ " return myNamespace::testCall3();\n"
+ " }\n"
+ " \n"
+ " myNamespace function testCall6() : String\n"
+ " {\n"
+ " return \"y\";\n"
+ " }\n"
+ " \n"
+ " public function testCall2() : String\n"
+ " {\n"
+ " return \"2\";\n"
+ " }\n"
+ " \n"
+ " private function testCall3() : String\n"
+ " {\n"
+ " return \"3\";\n"
+ " }\n"
+ " \n"
+ " protected function testCall4() : String\n"
+ " {\n"
+ " return \"4\";\n"
+ " }\n"
+ " \n"
+ " internal function testCall6() : String\n"
+ " {\n"
+ " return \"6\";\n"
+ " }\n"
+ " }\n"
+ "import tests_classes.mypackage2.TestClass;\n"
+ "import tests_classes.mypackage3.TestClass;\n"
+ "use namespace myNamespace;\n"
+ "public class TestClass2\n"
+ "{\n"
+ "public function TestClass2()\n"
+ "{\n"
+ "super();\n"
+ "}\n"
+ "");
+ "myNamespace static function testCall5() : String\n"
+ "{\n"
+ "return \"x\";\n"
+ "}\n"
+ "protected static function testCall5() : String\n"
+ "{\n"
+ "return \"5\";\n"
+ "}\n"
+ "public function testCall() : String\n"
+ "{\n"
+ "var a:tests_classes.mypackage1.TestClass = null;\n"
+ "var b:tests_classes.mypackage2.TestClass = null;\n"
+ "var c:tests_classes.mypackage3.TestClass = null;\n"
+ "a = new tests_classes.mypackage1.TestClass();\n"
+ "b = new tests_classes.mypackage2.TestClass();\n"
+ "c = new tests_classes.mypackage3.TestClass();\n"
+ "var res:String = a.testCall() + b.testCall() + c.testCall() + this.testCall2() + this.testCall3() + this.testCall4() + testCall5() + this.testCall6() + myNamespace::testCall3();\n"
+ "trace(res);\n"
+ "return res;\n"
+ "}\n"
+ "myNamespace function testCall2() : String\n"
+ "{\n"
+ "return \"1\";\n"
+ "}\n"
+ "myNamespace function testCall3() : String\n"
+ "{\n"
+ "return myNamespace::testCall2();\n"
+ "}\n"
+ "myNamespace function testCall4() : String\n"
+ "{\n"
+ "return myNamespace::testCall3();\n"
+ "}\n"
+ "myNamespace function testCall6() : String\n"
+ "{\n"
+ "return \"y\";\n"
+ "}\n"
+ "public function testCall2() : String\n"
+ "{\n"
+ "return \"2\";\n"
+ "}\n"
+ "private function testCall3() : String\n"
+ "{\n"
+ "return \"3\";\n"
+ "}\n"
+ "protected function testCall4() : String\n"
+ "{\n"
+ "return \"4\";\n"
+ "}\n"
+ "internal function testCall6() : String\n"
+ "{\n"
+ "return \"6\";\n"
+ "}\n"
+ "}\n"
+ "}");
}
@Test