Added: AS3 - navigation to definition in other SWF file and also player/airglobal

This commit is contained in:
Jindra Petřík
2025-06-01 13:09:09 +02:00
parent 9dff6b0efa
commit c9216538be
20 changed files with 575 additions and 152 deletions

View File

@@ -797,7 +797,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
if (Configuration.getPlayerSWC() != null) {
SWC swc = new SWC(Configuration.getPlayerSWC());
//set allowRenameIdentifiers parameter to FALSE otherwise there will be an infinite loop
SWF swf = new SWF(swc.getOpenable("library.swf"), null, null, null, true, false, true, null, "WINDOWS-1252", false);
SWF swf = new SWF(swc.getOpenable("library.swf"), null, "__playerglobal", null, true, false, true, null, "WINDOWS-1252", false);
playerGlobalAbcIndex = new AbcIndexing(swf);
}
}
@@ -805,12 +805,12 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
if (Configuration.getAirSWC() != null) {
SWC swc = new SWC(Configuration.getAirSWC());
//set allowRenameIdentifiers to FALSE
SWF swf = new SWF(swc.getOpenable("library.swf"), null, null, null, true, false, true, null, "WINDOWS-1252", false);
SWF swf = new SWF(swc.getOpenable("library.swf"), null, "__airglobal", null, true, false, true, null, "WINDOWS-1252", false);
airGlobalAbcIndex = new AbcIndexing(swf);
}
}
}
/**
* Gets SWF charset. SWF version 5 or lower were non-unicode. SWF object has
* assigned charset.

View File

@@ -384,6 +384,11 @@ public final class AbcIndexing {
* Object type
*/
public GraphTargetItem objType;
/**
* Script index
*/
public int scriptIndex;
/**
* Constructs trait index
@@ -393,14 +398,16 @@ public final class AbcIndexing {
* @param callType Call type
* @param value Value
* @param objType Object type
* @param scriptIndex Script index
*/
public TraitIndex(Trait trait, ABC abc, GraphTargetItem type, GraphTargetItem callType, ValueKind value, GraphTargetItem objType) {
public TraitIndex(Trait trait, ABC abc, GraphTargetItem type, GraphTargetItem callType, ValueKind value, GraphTargetItem objType, int scriptIndex) {
this.trait = trait;
this.abc = abc;
this.returnType = type;
this.callReturnType = callType;
this.value = value;
this.objType = objType;
this.scriptIndex = scriptIndex;
}
}
@@ -775,7 +782,7 @@ public final class AbcIndexing {
*/
//search all static first
if (findStatic && classProperties.containsKey(prop)) {
TraitIndex ti = classProperties.get(prop);
TraitIndex ti = classProperties.get(prop);
if (ti != null) {
foundStatic.setVal(true);
return ti;
@@ -933,7 +940,7 @@ public final class AbcIndexing {
* @param map Map to index
* @param mapNs Map to index
*/
protected void indexTraits(ABC abc, int name_index, Traits ts, Map<PropertyDef, TraitIndex> map, Map<PropertyNsDef, TraitIndex> mapNs) {
protected void indexTraits(ABC abc, int name_index, Traits ts, Map<PropertyDef, TraitIndex> map, Map<PropertyNsDef, TraitIndex> mapNs, int scriptIndex) {
for (Trait t : ts.traits) {
ValueKind propValue = null;
if (t instanceof TraitSlotConst) {
@@ -942,12 +949,12 @@ public final class AbcIndexing {
}
if (map != null) {
PropertyDef dp = new PropertyDef(t.getName(abc).getName(abc.constants, new ArrayList<>() /*?*/, true, false), multinameToType(name_index, abc.constants), abc, abc.constants.getMultiname(t.name_index).namespace_index);
map.put(dp, new TraitIndex(t, abc, getTraitReturnType(abc, t), getTraitCallReturnType(abc, t), propValue, multinameToType(name_index, abc.constants)));
map.put(dp, new TraitIndex(t, abc, getTraitReturnType(abc, t), getTraitCallReturnType(abc, t), propValue, multinameToType(name_index, abc.constants), scriptIndex));
}
if (mapNs != null) {
Multiname m = abc.constants.getMultiname(t.name_index);
PropertyNsDef ndp = new PropertyNsDef(t.getName(abc).getName(abc.constants, new ArrayList<>() /*?*/, true, true/*FIXME ???*/), m == null || m.namespace_index == 0 ? DottedChain.EMPTY : m.getNamespace(abc.constants).getName(abc.constants), abc, m == null ? 0 : m.namespace_index);
TraitIndex ti = new TraitIndex(t, abc, getTraitReturnType(abc, t), getTraitCallReturnType(abc, t), propValue, multinameToType(name_index, abc.constants));
TraitIndex ti = new TraitIndex(t, abc, getTraitReturnType(abc, t), getTraitCallReturnType(abc, t), propValue, multinameToType(name_index, abc.constants), scriptIndex);
if (!mapNs.containsKey(ndp)) {
mapNs.put(ndp, ti);
}
@@ -1038,7 +1045,7 @@ public final class AbcIndexing {
List<ClassIndex> addedClasses = new ArrayList<>();
for (int i = 0; i < abc.script_info.size(); i++) {
indexTraits(abc, 0, abc.script_info.get(i).traits, null, scriptProperties);
indexTraits(abc, 0, abc.script_info.get(i).traits, null, scriptProperties, i);
for (int t = 0; t < abc.script_info.get(i).traits.traits.size(); t++) {
Trait tr = abc.script_info.get(i).traits.traits.get(t);
if (tr instanceof TraitClass) {
@@ -1055,8 +1062,8 @@ public final class AbcIndexing {
GraphTargetItem cname = multinameToType(ii.name_index, abc.constants);
classes.put(new ClassDef(cname, abc, classScriptIndex), cindex);
indexTraits(abc, ii.name_index, ii.instance_traits, instanceProperties, instanceNsProperties);
indexTraits(abc, ii.name_index, ci.static_traits, classProperties, classNsProperties);
indexTraits(abc, ii.name_index, ii.instance_traits, instanceProperties, instanceNsProperties, i);
indexTraits(abc, ii.name_index, ci.static_traits, classProperties, classNsProperties, i);
}
}
}

View File

@@ -811,7 +811,8 @@ public class ActionScript3SimpleParser implements SimpleParser {
List<List<NamespaceItem>> allOpenedNamespaces,
ABC abc,
Reference<Boolean> sinitNeedsActivation,
List<VariableOrScope> sinitVariables
List<VariableOrScope> sinitVariables,
List<String> externalTypes
) throws AVM2ParseException, SimpleParseException, IOException, CompilationException, InterruptedException {
Stack<Loop> sinitLoops = new Stack<>();
@@ -828,7 +829,8 @@ public class ActionScript3SimpleParser implements SimpleParser {
sinitLoops,
sinitLoopLabels,
sinitRegisterVars,
sinitVariables
sinitVariables,
externalTypes
)) {
//empty
}
@@ -844,7 +846,8 @@ public class ActionScript3SimpleParser implements SimpleParser {
Stack<Loop> sinitLoops,
Map<Loop, String> sinitLoopLabels,
HashMap<String, Integer> sinitRegisterVars,
List<VariableOrScope> sinitVariables
List<VariableOrScope> sinitVariables,
List<String> externalTypes
) throws AVM2ParseException, SimpleParseException, SimpleParseException, IOException, CompilationException, InterruptedException {
ParsedSymbol s;
boolean inPackage = false;
@@ -872,7 +875,13 @@ public class ActionScript3SimpleParser implements SimpleParser {
allOpenedNamespaces.add(openedNamespaces);
parseImportsUsages(errors, sinitVariables, importedClasses, openedNamespaces, abc);
for (String name : abc.getSwf().getAbcIndex().getPackageObjects(pkgName)) {
externalTypes.add(pkgName.add(name, "").toRawString());
}
parseImportsUsages(errors, sinitVariables, importedClasses, openedNamespaces, abc, externalTypes);
boolean isEmpty = true;
@@ -1061,7 +1070,7 @@ public class ActionScript3SimpleParser implements SimpleParser {
lexer.pushback(preSymbols.get(i));
}
if (parseImportsUsages(errors, sinitVariables, importedClasses, openedNamespaces, abc)) {
if (parseImportsUsages(errors, sinitVariables, importedClasses, openedNamespaces, abc, externalTypes)) {
break;
}
boolean cmd = command(errors, null, sinitNeedsActivation, importedClasses, openedNamespaces, sinitLoops, sinitLoopLabels, sinitRegisterVars, true, false, true, 0, false, sinitVariables, abc);
@@ -2006,7 +2015,7 @@ public class ActionScript3SimpleParser implements SimpleParser {
private ActionScriptLexer lexer = null;
private boolean parseImportsUsages(List<SimpleParseException> errors, List<VariableOrScope> variables, List<DottedChain> importedClasses, List<NamespaceItem> openedNamespaces, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException {
private boolean parseImportsUsages(List<SimpleParseException> errors, List<VariableOrScope> variables, List<DottedChain> importedClasses, List<NamespaceItem> openedNamespaces, ABC abc, List<String> externalTypes) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException {
boolean isEmpty = true;
ParsedSymbol s;
@@ -2023,6 +2032,8 @@ public class ActionScript3SimpleParser implements SimpleParser {
s = lex();
boolean isStar = false;
int varPos = -1;
List<String> nameParts = new ArrayList<>();
nameParts.add(lastName);
while (s.type == SymbolType.DOT) {
s = lex();
if (s.type == SymbolType.MULTIPLY) {
@@ -2034,13 +2045,16 @@ public class ActionScript3SimpleParser implements SimpleParser {
fullName = fullName + "." + s.value.toString();
lastName = s.value.toString();
varPos = s.position;
nameParts.add(lastName);
s = lex();
}
if (isStar) {
//openedNamespaces.add(new NamespaceItem(fullName, Namespace.KIND_PACKAGE));
for (String n : abc.getSwf().getAbcIndex().getPackageObjects(new DottedChain(nameParts))) {
externalTypes.add(fullName + "." + n);
}
} else {
//importedClasses.add(fullName);
externalTypes.add(fullName);
variables.add(new Import(fullName, lastName, varPos));
}
expected(errors, s, lexer.yyline(), SymbolType.SEMICOLON);
@@ -2128,9 +2142,10 @@ public class ActionScript3SimpleParser implements SimpleParser {
List<List<NamespaceItem>> allOpenedNamespaces,
ABC abc,
Reference<Boolean> sinitNeedsActivation,
List<VariableOrScope> sinitVariables
List<VariableOrScope> sinitVariables,
List<String> externalTypes
) throws IOException, AVM2ParseException, SimpleParseException, CompilationException, InterruptedException {
scriptTraits(errors, importedClasses, openedNamespaces, allOpenedNamespaces, abc, sinitNeedsActivation, sinitVariables);
scriptTraits(errors, importedClasses, openedNamespaces, allOpenedNamespaces, abc, sinitNeedsActivation, sinitVariables, externalTypes);
}
/**
@@ -2157,11 +2172,12 @@ public class ActionScript3SimpleParser implements SimpleParser {
String str,
ABC abc,
Reference<Boolean> sinitNeedsActivation,
List<VariableOrScope> sinitVariables
List<VariableOrScope> sinitVariables,
List<String> externalTypes
) throws AVM2ParseException, SimpleParseException, IOException, CompilationException, InterruptedException {
lexer = new ActionScriptLexer(str);
parseScript(errors, importedClasses, openedNamespaces, allOpenedNamespaces, abc, sinitNeedsActivation, sinitVariables);
parseScript(errors, importedClasses, openedNamespaces, allOpenedNamespaces, abc, sinitNeedsActivation, sinitVariables, externalTypes);
ParsedSymbol s = lexer.lex();
if (s.type != SymbolType.EOF) {
errors.add(new SimpleParseException("Parsing finished before end of the file", lexer.yyline(), s.position));
@@ -2173,15 +2189,22 @@ public class ActionScript3SimpleParser implements SimpleParser {
String str,
Map<Integer, List<Integer>> definitionPosToReferences,
Map<Integer, Integer> referenceToDefinition,
List<SimpleParseException> errors
List<SimpleParseException> errors,
List<String> externalTypes,
Map<Integer, Integer> referenceToExternalTypeIndex,
Map<Integer, List<Integer>> externalTypeIndexToReference
) throws SimpleParseException, IOException, InterruptedException {
List<List<NamespaceItem>> allOpenedNamespaces = new ArrayList<>();
Reference<Boolean> sinitNeedsActivation = new Reference<>(false);
List<VariableOrScope> vars = new ArrayList<>();
List<DottedChain> importedClasses = new ArrayList<>();
List<NamespaceItem> openedNamespaces = new ArrayList<>();
for (String name : abc.getSwf().getAbcIndex().getPackageObjects(DottedChain.TOPLEVEL)) {
externalTypes.add(name);
}
externalTypes.add("__AS3__.vec.Vector");
try {
scriptTraitsFromString(errors, importedClasses, openedNamespaces, allOpenedNamespaces, str, abc, sinitNeedsActivation, vars);
scriptTraitsFromString(errors, importedClasses, openedNamespaces, allOpenedNamespaces, str, abc, sinitNeedsActivation, vars, externalTypes);
} catch (AVM2ParseException ex) {
//Logger.getLogger(ActionScript3SimpleParser.class.getName()).log(Level.SEVERE, null, ex);
throw new SimpleParseException(str, ex.line, ex.position);
@@ -2189,7 +2212,7 @@ public class ActionScript3SimpleParser implements SimpleParser {
//Logger.getLogger(ActionScript3SimpleParser.class.getName()).log(Level.SEVERE, null, ex);
throw new SimpleParseException(str, ex.line);
}
SimpleParser.parseVariablesList(new ArrayList<>(), vars, definitionPosToReferences, referenceToDefinition, errors, true);
SimpleParser.parseVariablesList(new ArrayList<>(), vars, definitionPosToReferences, referenceToDefinition, errors, true, externalTypes, referenceToExternalTypeIndex, externalTypeIndexToReference);
}
/**

View File

@@ -1570,9 +1570,12 @@ public class ActionScript2SimpleParser implements SimpleParser {
String str,
Map<Integer, List<Integer>> definitionPosToReferences,
Map<Integer, Integer> referenceToDefinition,
List<SimpleParseException> errors
List<SimpleParseException> errors,
List<String> externalTypes,
Map<Integer, Integer> referenceToExternalTypeIndex,
Map<Integer, List<Integer>> externalTypeIndexToReference
) throws SimpleParseException, IOException, InterruptedException {
List<VariableOrScope> vars = new ArrayList<>();
try {
lexer = new ActionScriptLexer(new StringReader(str));
@@ -1661,7 +1664,7 @@ public class ActionScript2SimpleParser implements SimpleParser {
} catch (ActionParseException ex) {
errors.add(new SimpleParseException(ex.getMessage(), ex.line, ex.position));
}
SimpleParser.parseVariablesList(new ArrayList<>(), vars, definitionPosToReferences, referenceToDefinition, errors, false);
SimpleParser.parseVariablesList(new ArrayList<>(), vars, definitionPosToReferences, referenceToDefinition, errors, false, externalTypes, referenceToExternalTypeIndex, externalTypeIndexToReference);
}
private void versionRequired(List<SimpleParseException> errors, ParsedSymbol s, int min) throws SimpleParseException {

View File

@@ -27,14 +27,9 @@ import com.jpexs.helpers.Helper;
import com.jpexs.helpers.Path;
import java.awt.Color;
import java.awt.Font;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URISyntaxException;
import java.util.ArrayList;
@@ -1145,6 +1140,11 @@ public final class Configuration {
@ConfigurationDefaultBoolean(false)
@ConfigurationCategory("display")
public static ConfigurationItem<Boolean> snapAlignCenterAlignmentVertical = null;
@ConfigurationDefaultBoolean(true)
@ConfigurationName("warning.linkTypes")
@ConfigurationCategory("script")
public static ConfigurationItem<Boolean> warningLinkTypes = null;
private static Map<String, String> configurationDescriptions = new LinkedHashMap<>();
private static Map<String, String> configurationTitles = new LinkedHashMap<>();

View File

@@ -45,7 +45,10 @@ public interface SimpleParser {
String str,
Map<Integer, List<Integer>> definitionPosToReferences,
Map<Integer, Integer> referenceToDefinition,
List<SimpleParseException> errors
List<SimpleParseException> errors,
List<String> externalTypes,
Map<Integer, Integer> referenceToExternalTypeIndex,
Map<Integer, List<Integer>> externalTypeIndexToReference
) throws SimpleParseException, IOException, InterruptedException;
public static void parseVariablesList(
@@ -54,9 +57,22 @@ public interface SimpleParser {
Map<Integer, List<Integer>> definitionPosToReferences,
Map<Integer, Integer> referenceToDefinition,
List<SimpleParseException> errors,
boolean innerFunctionCanUseTraits
boolean innerFunctionCanUseTraits,
List<String> externalTypes,
Map<Integer, Integer> referenceToExternalTypeIndex,
Map<Integer, List<Integer>> externalTypeIndexToReference
) {
parseVariablesList(privateVariables, sharedVariables, definitionPosToReferences, referenceToDefinition, new LinkedHashMap<>(), new LinkedHashMap<>(), new LinkedHashMap<>(), true, errors, null, innerFunctionCanUseTraits);
List<String> externalSimpleTypes = new ArrayList<>();
for (String type : externalTypes) {
externalSimpleTypes.add(type.contains(".") ? type.substring(type.lastIndexOf(".") + 1) : type);
}
parseVariablesList(privateVariables, sharedVariables, definitionPosToReferences, referenceToDefinition, new LinkedHashMap<>(), new LinkedHashMap<>(), new LinkedHashMap<>(), true, errors, null, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex);
for (Map.Entry<Integer, Integer> entry : referenceToExternalTypeIndex.entrySet()) {
if (!externalTypeIndexToReference.containsKey(entry.getValue())) {
externalTypeIndexToReference.put(entry.getValue(), new ArrayList<>());
}
externalTypeIndexToReference.get(entry.getValue()).add(entry.getKey());
}
}
public static void parseVariablesList(
@@ -70,7 +86,9 @@ public interface SimpleParser {
boolean isStatic,
List<SimpleParseException> errors,
Scope scope,
boolean innerFunctionCanUseTraits
boolean innerFunctionCanUseTraits,
List<String> externalSimpleTypes,
Map<Integer, Integer> referenceToExternalTypeIndex
) {
Map<String, Integer> privateVarNameToDefinitionPosition = new LinkedHashMap<>();
privateVarNameToDefinitionPosition.putAll(parentVarNameToDefinitionPosition);
@@ -89,13 +107,18 @@ public interface SimpleParser {
} else {
if (!privateVarFullNameToDefinitionPosition.containsKey(v.name)
&& !privateVarNameToDefinitionPosition.containsKey(v.name)) {
parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1);
parentVarNameToDefinitionPosition.put(v.getLastName(), -v.position - 1);
privateVarFullNameToDefinitionPosition.put(v.name, -v.position - 1);
privateVarNameToDefinitionPosition.put(v.getLastName(), -v.position - 1);
definitionPosToReferences.put(-v.position - 1, new ArrayList<>());
definitionPosToReferences.get(-v.position - 1).add(v.position);
referenceToDefinition.put(v.position, -v.position - 1);
if (externalSimpleTypes.contains(v.name)) {
referenceToExternalTypeIndex.put(v.position, externalSimpleTypes.indexOf(v.name));
} else {
parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1);
parentVarNameToDefinitionPosition.put(v.getLastName(), -v.position - 1);
privateVarFullNameToDefinitionPosition.put(v.name, -v.position - 1);
privateVarNameToDefinitionPosition.put(v.getLastName(), -v.position - 1);
definitionPosToReferences.put(-v.position - 1, new ArrayList<>());
definitionPosToReferences.get(-v.position - 1).add(v.position);
referenceToDefinition.put(v.position, -v.position - 1);
}
} else {
if ("this".equals(v.name) && isStatic) {
@@ -149,7 +172,7 @@ public interface SimpleParser {
}
}
parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, subPrivateVarFullNameToDefinitionPosition, subPrivateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits);
parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, subPrivateVarFullNameToDefinitionPosition, subPrivateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex);
}
}
for (VariableOrScope vt : sharedVariables) {
@@ -165,13 +188,18 @@ public interface SimpleParser {
} else {
if (!privateVarFullNameToDefinitionPosition.containsKey(v.name)
&& !privateVarNameToDefinitionPosition.containsKey(v.name)) {
parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1);
parentVarNameToDefinitionPosition.put(v.getFirstName(), -v.position - 1);
privateVarFullNameToDefinitionPosition.put(v.name, -v.position - 1);
privateVarNameToDefinitionPosition.put(v.getFirstName(), -v.position - 1);
definitionPosToReferences.put(-v.position - 1, new ArrayList<>());
definitionPosToReferences.get(-v.position - 1).add(v.position);
referenceToDefinition.put(v.position, -v.position - 1);
if (externalSimpleTypes.contains(v.name)) {
referenceToExternalTypeIndex.put(v.position, externalSimpleTypes.indexOf(v.name));
} else {
parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1);
parentVarNameToDefinitionPosition.put(v.getFirstName(), -v.position - 1);
privateVarFullNameToDefinitionPosition.put(v.name, -v.position - 1);
privateVarNameToDefinitionPosition.put(v.getFirstName(), -v.position - 1);
definitionPosToReferences.put(-v.position - 1, new ArrayList<>());
definitionPosToReferences.get(-v.position - 1).add(v.position);
referenceToDefinition.put(v.position, -v.position - 1);
}
} else {
if ("this".equals(v.name) && isStatic) {
@@ -225,7 +253,7 @@ public interface SimpleParser {
}
}
parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits);
parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex);
}
}
}