diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java
index c0211c047..1c4880084 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java
@@ -2502,6 +2502,7 @@ public final class SWF implements SWFContainerItem, Timelined {
}
public void clearImageCache() {
+ jtt = null;
frameCache.clear();
rectCache.clear();
for (Tag tag : getTags()) {
@@ -2898,8 +2899,7 @@ public final class SWF implements SWFContainerItem, Timelined {
timelined.setModified(true);
timelined.resetTimeline();
} else // timeline should be always the swf here
- {
- if (removeDependencies) {
+ if (removeDependencies) {
removeTagWithDependenciesFromTimeline(tag, timelined.getTimeline());
timelined.setModified(true);
} else {
@@ -2908,7 +2908,6 @@ public final class SWF implements SWFContainerItem, Timelined {
timelined.setModified(true);
}
}
- }
}
@Override
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java
index 6a9ffdacf..fef18dfc8 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java
@@ -56,19 +56,15 @@ import com.jpexs.decompiler.flash.abc.usages.MethodParamsMultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.MethodReturnTypeMultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.MultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.TypeNameMultinameUsage;
-import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.dumpview.DumpInfo;
import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecial;
import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecialType;
-import com.jpexs.decompiler.flash.exporters.script.LinkReportExporter;
-import com.jpexs.decompiler.flash.flexsdk.MxmlcAs3ScriptReplacer;
-import com.jpexs.decompiler.flash.flexsdk.MxmlcException;
import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
+import com.jpexs.decompiler.flash.importers.As3ScriptReplaceException;
import com.jpexs.decompiler.flash.importers.As3ScriptReplacerInterface;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.types.annotations.Internal;
-import com.jpexs.decompiler.graph.CompilationException;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.helpers.utf8.Utf8PrintWriter;
import java.io.IOException;
@@ -1405,7 +1401,7 @@ public class ABC {
method_info.remove(index);
}
- public boolean replaceScriptPack(As3ScriptReplacerInterface replacer, ScriptPack pack, String as) throws AVM2ParseException, CompilationException, IOException, InterruptedException {
+ public boolean replaceScriptPack(As3ScriptReplacerInterface replacer, ScriptPack pack, String as) throws As3ScriptReplaceException, IOException, InterruptedException {
replacer.replaceScript(pack, as);
((Tag) parentTag).setModified(true);
return pack.isSimple;
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfToSwcExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfToSwcExporter.java
index 69fed58d3..7622c807a 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfToSwcExporter.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfToSwcExporter.java
@@ -6,6 +6,7 @@ import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.ClassPath;
import com.jpexs.decompiler.flash.abc.ScriptPack;
+import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.script.Dependency;
import com.jpexs.decompiler.flash.exporters.script.DependencyType;
import com.jpexs.decompiler.flash.importers.SwfXmlImporter;
@@ -127,14 +128,15 @@ public class SwfToSwcExporter {
String defId = dottedChainToId(cp.packageStr.add(cp.className));
sb.append(" \n");
- List dependencies = new ArrayList<>();
- List uses = new ArrayList<>();
- pack.abc.script_info.get(pack.scriptIndex).traits.getDependencies(null, pack.abc, dependencies, uses, new DottedChain("NO:PACKAGE"), new ArrayList<>());
Set allDeps = new HashSet<>();
allDeps.add(new DottedChain("AS3"));
sb.append(" \n");
if (!skipDependencies) {
+ List dependencies = new ArrayList<>();
+ List uses = new ArrayList<>();
+ pack.abc.script_info.get(pack.scriptIndex).traits.getDependencies(null, pack.abc, dependencies, uses, new DottedChain("NO:PACKAGE"), new ArrayList<>());
+
for (Dependency d : dependencies) {
if ("*".equals(d.getId().getLast())) {
continue;
@@ -185,14 +187,22 @@ public class SwfToSwcExporter {
private SWF recompileSWF(SWF swf) throws IOException, InterruptedException {
ByteArrayOutputStream swfOrigBaos = new ByteArrayOutputStream();
swf.saveTo(swfOrigBaos);
- return new SWF(new ByteArrayInputStream(swfOrigBaos.toByteArray()), false, false);
+ return new SWF(new ByteArrayInputStream(swfOrigBaos.toByteArray()), Configuration.parallelSpeedUp.get(), false);
+ }
+
+ private static void printDelay(String title, long t1, long t2) {
+ //System.out.println("time " + title + ": " + (t2 - t1));
}
public void exportSwf(SWF swf, File outSwcFile, boolean skipDependencies) throws IOException {
-
+ long t4 = 0;
//Make local copy of SWF so we do not modify original
try {
+ long t1 = System.currentTimeMillis();
swf = recompileSWF(swf);
+ long t2 = System.currentTimeMillis();
+ printDelay("swc.recompile", t1, t2);
+
final String HASH = "myhash";
String abcTagXml = new String(Helper.readStream(SwfToSwcExporter.class.getResourceAsStream("/com/jpexs/decompiler/flash/exporters/swf/swc_main_abctag.xml")), "UTF-8");
abcTagXml = abcTagXml.replace("%hash%", HASH);
@@ -208,6 +218,7 @@ public class SwfToSwcExporter {
break;
}
}
+
for (int i = 0; i < list.size(); i++) {
if (list.get(i) instanceof SymbolClassTag) {
SymbolClassTag sct = (SymbolClassTag) list.get(i);
@@ -220,20 +231,33 @@ public class SwfToSwcExporter {
}
}
}
+ long t3 = System.currentTimeMillis();
+ printDelay("swc.documentTag", t2, t3);
+
if (!documentClassSet) {
throw new IOException("Original document class not found!");
}
swf = recompileSWF(swf);
+ t4 = System.currentTimeMillis();
+ printDelay("swc.recompile2", t3, t4);
} catch (Exception ex) {
+ ex.printStackTrace();
+ System.exit(0);
throw new RuntimeException(ex);
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
swf.saveTo(baos);
byte[] swfBytes = baos.toByteArray();
+ long t5 = System.currentTimeMillis();
+ printDelay("swc.getBytes", t4, t5);
+
String catalogStr = generateCatalog(swf, swfBytes, skipDependencies);
+ long t6 = System.currentTimeMillis();
+ printDelay("swc.generateCatalog", t5, t6);
+
File tempFile = new File((outSwcFile.getAbsolutePath()) + ".tmp");
FileOutputStream fos = null;
ZipOutputStream zos = null;
@@ -277,6 +301,8 @@ public class SwfToSwcExporter {
tempFile.delete();
}
}
+ long t7 = System.currentTimeMillis();
+ printDelay("swc.zip", t6, t7);
}
}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/MxmlcAs3ScriptReplacer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/MxmlcAs3ScriptReplacer.java
index 22c09859a..f450c2e16 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/MxmlcAs3ScriptReplacer.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/MxmlcAs3ScriptReplacer.java
@@ -14,6 +14,8 @@ import com.jpexs.decompiler.flash.exporters.script.AS3ScriptExporter;
import com.jpexs.decompiler.flash.exporters.script.LinkReportExporter;
import com.jpexs.decompiler.flash.exporters.settings.ScriptExportSettings;
import com.jpexs.decompiler.flash.exporters.swf.SwfToSwcExporter;
+import com.jpexs.decompiler.flash.importers.As3ScriptReplaceException;
+import com.jpexs.decompiler.flash.importers.As3ScriptReplaceExceptionItem;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.graph.CompilationException;
@@ -31,14 +33,22 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.jpexs.decompiler.flash.importers.As3ScriptReplacerInterface;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public class MxmlcAs3ScriptReplacer extends MxmlcRunner implements As3ScriptReplacerInterface {
- private LinkReportExporter linkReporter;
+ private ScriptPack initedPack;
+ private File tempDir;
+ private File pkgDir;
+ private File swcFile;
- public MxmlcAs3ScriptReplacer(String flexSdkPath, LinkReportExporter linkReporter) {
+ public MxmlcAs3ScriptReplacer(String flexSdkPath) {
super(flexSdkPath);
- this.linkReporter = linkReporter;
+ }
+
+ private synchronized boolean isInited(ScriptPack pack) {
+ return tempDir != null && initedPack == pack;
}
private static void deleteFolder(File folder) {
@@ -58,7 +68,7 @@ public class MxmlcAs3ScriptReplacer extends MxmlcRunner implements As3ScriptRepl
private SWF recompileSWF(SWF swf) throws IOException, InterruptedException {
ByteArrayOutputStream swfOrigBaos = new ByteArrayOutputStream();
swf.saveTo(swfOrigBaos);
- return new SWF(new ByteArrayInputStream(swfOrigBaos.toByteArray()), false, false);
+ return new SWF(new ByteArrayInputStream(swfOrigBaos.toByteArray()), Configuration.parallelSpeedUp.get(), false);
}
private boolean isParentDeleted(ABC abc, List allAbcs, DottedChain className) {
@@ -91,27 +101,157 @@ public class MxmlcAs3ScriptReplacer extends MxmlcRunner implements As3ScriptRepl
}
@Override
- public void replaceScript(ScriptPack pack, String text) throws AVM2ParseException, CompilationException, IOException, InterruptedException {
+ public synchronized void replaceScript(ScriptPack pack, String text) throws As3ScriptReplaceException, IOException, InterruptedException {
if (!pack.isSimple) {
- throw new IOException("Cannot compile such file"); //Alchemy, etc.
+ throw new IOException("Cannot compile such file"); //Alchemy, etc. TODO: handle better
}
- File tempDir = null;
+ if (!isInited(pack)) {
+ initReplacement(pack);
+ }
+
+ File scriptFileToCompile = new File(pkgDir, pack.getClassPath().className + ".as");
+ //Write new script
+ Helper.writeFile(scriptFileToCompile.getAbsolutePath(), text.getBytes("UTF-8"));
+ File compiledSwfFile = new File(pkgDir, "out.swf");
+
+ try {
+ //Compile it (and subclasses stubs)
+ mxmlc("-strict=false", "-include-inheritance-dependencies-only", "-warnings=false", "-library-path", swcFile.getAbsolutePath(), "-source-path", tempDir.getAbsolutePath(), "-output", compiledSwfFile.getAbsolutePath(), "-debug=true", scriptFileToCompile.getAbsolutePath());
+ } catch (MxmlcException ex1) {
+ //String compiledFilePath = scriptFileToCompile.getAbsolutePath();
+ Pattern errPattern = Pattern.compile("^" + Pattern.quote(tempDir.getAbsolutePath()) + "(?.*)\\((?[0-9]+)\\): col: (?[0-9]+) (?.*)$");
+ String err = ex1.getMxmlcErrorOutput();
+ String errLines[] = err.split("\r?\n");
+ List errorItems = new ArrayList<>();
+ for (int i = 0; i < errLines.length; i++) {
+ String line = errLines[i].trim();
+ Matcher m = errPattern.matcher(line);
+ if (m.matches()) {
+ String errFile = m.group("file");
+ int errLine = Integer.parseInt(m.group("line"));
+ int errCol = Integer.parseInt(m.group("col"));
+ String errMsg = m.group("message");
+ errorItems.add(new As3ScriptReplaceExceptionItem(errFile, errMsg, errLine, errCol));
+ }
+ }
+ throw new As3ScriptReplaceException(errorItems);
+ }
+
+ try (FileInputStream fis = new FileInputStream(compiledSwfFile)) {
+ SWF newSWF = new SWF(fis, false, false);
+ List newTags = newSWF.getAbcList();
+ int oldScriptIndex = pack.scriptIndex;
+ int oldClassIndex = -1;
+
+ ScriptInfo oldScriptInfo = pack.abc.script_info.get(pack.scriptIndex);
+ for (Trait t : oldScriptInfo.traits.traits) {
+ if (t instanceof TraitClass) {
+ int traitClassIndex = ((TraitClass) t).class_info;
+ if (oldClassIndex == -1 || traitClassIndex < oldClassIndex) {
+ oldClassIndex = traitClassIndex;
+ }
+ }
+ }
+ if (pack.isSimple) {
+ oldScriptInfo.delete(pack.abc, true);
+ } else {
+ //NOO
+ }
+ pack.abc.pack(); // removes old classes/methods/scripts
+ ABCContainerTag newTagsLast = newTags.get(newTags.size() - 1);
+ ABC newLastAbc = newTagsLast.getABC();
+ Map classesMap = new HashMap<>();
+ Map scriptsMap = new HashMap<>();
+
+ pack.abc.mergeABC(newLastAbc,
+ new HashMap<>(),
+ new HashMap<>(),
+ new HashMap<>(),
+ new HashMap<>(),
+ new HashMap<>(),
+ new HashMap<>(),
+ new HashMap<>(),
+ new HashMap<>(),
+ new HashMap<>(),
+ new HashMap<>(),
+ new HashMap<>(),
+ new HashMap<>(),
+ classesMap,
+ new HashMap<>(),
+ scriptsMap
+ );
+
+ //Reorder newly created scripts to be in place
+ //where old script was
+ List addedScriptIndices = new ArrayList<>(scriptsMap.values());
+ Collections.sort(addedScriptIndices);
+ List addedScripts = new ArrayList<>();
+ for (int i = addedScriptIndices.size() - 1; i >= 0; i--) {
+ int newScriptIndex = addedScriptIndices.get(i);
+ addedScripts.add(0, pack.abc.script_info.remove(newScriptIndex));
+ }
+ for (int i = 0; i < addedScripts.size(); i++) {
+ pack.abc.script_info.add(oldScriptIndex + i, addedScripts.get(i));
+ }
+
+ //IMPORTANT: Map newly created classes to their position as they
+ //were in original script because FlashPlayer needs
+ //parent class to be defined earlier
+ if (oldClassIndex > -1) {
+ List addedClassIndices = new ArrayList<>(classesMap.values());
+ Collections.sort(addedClassIndices);
+ int totalClassCount = pack.abc.class_info.size();
+ Map classesRemap = new HashMap<>();
+ for (int i = 0; i < addedClassIndices.size(); i++) {
+ classesRemap.put(addedClassIndices.get(i), oldClassIndex + i);
+ }
+ int mappingStart = oldClassIndex;
+ for (int i = oldClassIndex; i < totalClassCount; i++) {
+ if (!classesRemap.containsKey(i)) {
+ for (int j = mappingStart; j < totalClassCount; j++) {
+ if (!classesRemap.containsValue(j)) {
+ classesRemap.put(i, j);
+ mappingStart = j + 1;
+ break;
+ }
+ }
+ }
+ }
+ pack.abc.reorganizeClasses(classesRemap);
+ }
+ ((Tag) pack.abc.parentTag).setModified(true);
+ deinitReplacement(pack);//successfull finish
+ }
+
+ }
+
+ @Override
+ public boolean isAvailable() {
+ String flexLocation = Configuration.flexSdkLocation.get();
+ return !(flexLocation.isEmpty() || (!new File(MxmlcRunner.getMxmlcPath(flexLocation)).exists()));
+ }
+
+ @Override
+ public synchronized void initReplacement(ScriptPack pack) {
+ if (tempDir != null) {
+ deinitReplacement(pack);
+ }
try {
tempDir = Files.createTempDirectory("ffdec-mxmlc-replace").toFile();
- File pkgDir = tempDir;
+ pkgDir = tempDir;
for (String pkgPart : pack.getClassPath().packageStr.toList()) {
if (!pkgPart.isEmpty()) {
pkgDir = new File(pkgDir, pkgPart);
}
}
pkgDir.mkdirs();
- File scriptFileToCompile = new File(pkgDir, pack.getClassPath().className + ".as");
- File compiledSwfFile = new File(pkgDir, "out.swf");
- File swcFile = new File(pkgDir, "out.swc");
+
+ swcFile = new File(pkgDir, "out.swc");
//Make copy without the old script
SWF swfCopy = recompileSWF(pack.getSwf());
+
List modAbcs = new ArrayList<>();
List copyPacks = swfCopy.getAS3Packs();
@@ -135,6 +275,7 @@ public class MxmlcAs3ScriptReplacer extends MxmlcRunner implements As3ScriptRepl
removedPacks.add(sp);
}
}
+
//Export subclasses so they can be compiled by Flex, but ONLY STUBS.
//No method code to avoid code compilation problems.
//This compiled code won't be used at all in original SWF,
@@ -146,115 +287,25 @@ public class MxmlcAs3ScriptReplacer extends MxmlcRunner implements As3ScriptRepl
for (ABC a : modAbcs) {
a.pack();
}
+
//Generate SWC file from the modified SWF file.
//Flex then uses the code already present in the SWC, no need to decompile it (hurray!)
SwfToSwcExporter swcExport = new SwfToSwcExporter();
swcExport.exportSwf(swfCopy, swcFile, true);
- //Write new script
- Helper.writeFile(scriptFileToCompile.getAbsolutePath(), text.getBytes("UTF-8"));
-
- try {
- //Compile it (and subclasses stubs)
- mxmlc("-strict=false", "-include-inheritance-dependencies-only", "-warnings=false", "-library-path", swcFile.getAbsolutePath(), "-source-path", tempDir.getAbsolutePath(), "-output", compiledSwfFile.getAbsolutePath(), "-debug=true", scriptFileToCompile.getAbsolutePath());
- } catch (MxmlcException ex1) {
- throw new AVM2ParseException(ex1.getMxmlcErrorOutput(), 0);
- }
-
- try (FileInputStream fis = new FileInputStream(compiledSwfFile)) {
- SWF newSWF = new SWF(fis, false, false);
- List newTags = newSWF.getAbcList();
- int oldScriptIndex = pack.scriptIndex;
- int oldClassIndex = -1;
-
- ScriptInfo oldScriptInfo = pack.abc.script_info.get(pack.scriptIndex);
- for (Trait t : oldScriptInfo.traits.traits) {
- if (t instanceof TraitClass) {
- int traitClassIndex = ((TraitClass) t).class_info;
- if (oldClassIndex == -1 || traitClassIndex < oldClassIndex) {
- oldClassIndex = traitClassIndex;
- }
- }
- }
- if (pack.isSimple) {
- oldScriptInfo.delete(pack.abc, true);
- } else {
- //NOO
- }
- pack.abc.pack(); // removes old classes/methods/scripts
- ABCContainerTag newTagsLast = newTags.get(newTags.size() - 1);
- ABC newLastAbc = newTagsLast.getABC();
- Map classesMap = new HashMap<>();
- Map scriptsMap = new HashMap<>();
-
- pack.abc.mergeABC(newLastAbc,
- new HashMap<>(),
- new HashMap<>(),
- new HashMap<>(),
- new HashMap<>(),
- new HashMap<>(),
- new HashMap<>(),
- new HashMap<>(),
- new HashMap<>(),
- new HashMap<>(),
- new HashMap<>(),
- new HashMap<>(),
- new HashMap<>(),
- classesMap,
- new HashMap<>(),
- scriptsMap
- );
-
- //Reorder newly created scripts to be in place
- //where old script was
- List addedScriptIndices = new ArrayList<>(scriptsMap.values());
- Collections.sort(addedScriptIndices);
- List addedScripts = new ArrayList<>();
- for (int i = addedScriptIndices.size() - 1; i >= 0; i--) {
- int newScriptIndex = addedScriptIndices.get(i);
- addedScripts.add(0, pack.abc.script_info.remove(newScriptIndex));
- }
- for (int i = 0; i < addedScripts.size(); i++) {
- pack.abc.script_info.add(oldScriptIndex + i, addedScripts.get(i));
- }
-
- //IMPORTANT: Map newly created classes to their position as they
- //were in original script because FlashPlayer needs
- //parent class to be defined earlier
- if (oldClassIndex > -1) {
- List addedClassIndices = new ArrayList<>(classesMap.values());
- Collections.sort(addedClassIndices);
- int totalClassCount = pack.abc.class_info.size();
- Map classesRemap = new HashMap<>();
- for (int i = 0; i < addedClassIndices.size(); i++) {
- classesRemap.put(addedClassIndices.get(i), oldClassIndex + i);
- }
- int mappingStart = oldClassIndex;
- for (int i = oldClassIndex; i < totalClassCount; i++) {
- if (!classesRemap.containsKey(i)) {
- for (int j = mappingStart; j < totalClassCount; j++) {
- if (!classesRemap.containsValue(j)) {
- classesRemap.put(i, j);
- mappingStart = j + 1;
- break;
- }
- }
- }
- }
- pack.abc.reorganizeClasses(classesRemap);
- }
- ((Tag) pack.abc.parentTag).setModified(true);
- }
- } finally {
- if (tempDir != null && tempDir.exists()) {
- deleteFolder(tempDir);
- }
+ } catch (IOException iex) {
+ //ignore
+ } catch (InterruptedException ex) {
+ //ignore
}
+ this.initedPack = pack;
}
@Override
- public boolean isAvailable() {
- String flexLocation = Configuration.flexSdkLocation.get();
- return !(flexLocation.isEmpty() || (!new File(MxmlcRunner.getMxmlcPath(flexLocation)).exists()));
+ public synchronized void deinitReplacement(ScriptPack pack) {
+ if (tempDir != null && tempDir.exists()) {
+ deleteFolder(tempDir);
+ }
+ tempDir = null;
}
}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS3ScriptImporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS3ScriptImporter.java
index e43ed93c2..b423df89a 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS3ScriptImporter.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS3ScriptImporter.java
@@ -51,10 +51,10 @@ public class AS3ScriptImporter {
try {
pack.abc.replaceScriptPack(scriptReplacer, pack, txt);
- } catch (AVM2ParseException ex) {
- logger.log(Level.SEVERE, "%error% on line %line%, file: %file%".replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)).replace("%file%", fileName));
- } catch (CompilationException ex) {
- logger.log(Level.SEVERE, "%error% on line %line%, file: %file%".replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)).replace("%file%", fileName));
+ } catch (As3ScriptReplaceException asre) {
+ for (As3ScriptReplaceExceptionItem item : asre.getExceptionItems()) {
+ logger.log(Level.SEVERE, "%error% on line %line%, column %col%, file: %file%".replace("%error%", item.getMessage()).replace("%line%", Long.toString(item.getLine())).replace("%file%", fileName).replace("%col%", "" + item.getCol()));
+ }
} catch (InterruptedException ex) {
logger.log(Level.SEVERE, "error during script import, file: %file%".replace("%file%", fileName), ex);
}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplaceException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplaceException.java
new file mode 100644
index 000000000..a283ce9ee
--- /dev/null
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplaceException.java
@@ -0,0 +1,27 @@
+package com.jpexs.decompiler.flash.importers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author JPEXS
+ */
+public class As3ScriptReplaceException extends Exception {
+
+ private List exceptionItems;
+
+ public As3ScriptReplaceException(List exceptionItems) {
+ this.exceptionItems = exceptionItems;
+ }
+
+ public As3ScriptReplaceException(As3ScriptReplaceExceptionItem exceptionItem) {
+ this.exceptionItems = new ArrayList<>();
+ this.exceptionItems.add(exceptionItem);
+ }
+
+ public List getExceptionItems() {
+ return exceptionItems;
+ }
+
+}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplaceExceptionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplaceExceptionItem.java
new file mode 100644
index 000000000..771a29a72
--- /dev/null
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplaceExceptionItem.java
@@ -0,0 +1,44 @@
+package com.jpexs.decompiler.flash.importers;
+
+public class As3ScriptReplaceExceptionItem {
+
+ private String file;
+ private int line;
+ private int col;
+ private String message;
+
+ public static final int COL_UNKNOWN = -1;
+ public static final int LINE_UNKNOWN = -1;
+
+ public As3ScriptReplaceExceptionItem(String file, String message, int line) {
+ this(file, message, line, COL_UNKNOWN);
+ }
+
+ public As3ScriptReplaceExceptionItem(String file, String message) {
+ this(file, message, LINE_UNKNOWN, COL_UNKNOWN);
+ }
+
+ public As3ScriptReplaceExceptionItem(String file, String message, int line, int col) {
+ this.file = file;
+ this.line = line;
+ this.col = col;
+ this.message = message;
+ }
+
+ public String getFile() {
+ return file;
+ }
+
+ public int getLine() {
+ return line;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public int getCol() {
+ return col;
+ }
+
+}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplacerFactory.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplacerFactory.java
index d28c38213..ad7d0a718 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplacerFactory.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplacerFactory.java
@@ -1,7 +1,6 @@
package com.jpexs.decompiler.flash.importers;
import com.jpexs.decompiler.flash.configuration.Configuration;
-import com.jpexs.decompiler.flash.exporters.script.LinkReportExporter;
import com.jpexs.decompiler.flash.flexsdk.MxmlcAs3ScriptReplacer;
public class As3ScriptReplacerFactory {
@@ -15,7 +14,7 @@ public class As3ScriptReplacerFactory {
}
public static As3ScriptReplacerInterface createFlex() {
- return new MxmlcAs3ScriptReplacer(Configuration.flexSdkLocation.get(), new LinkReportExporter());
+ return new MxmlcAs3ScriptReplacer(Configuration.flexSdkLocation.get());
}
public static As3ScriptReplacerInterface createFFDec() {
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplacerInterface.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplacerInterface.java
index d14863048..de7de53ad 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplacerInterface.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplacerInterface.java
@@ -1,13 +1,15 @@
package com.jpexs.decompiler.flash.importers;
import com.jpexs.decompiler.flash.abc.ScriptPack;
-import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException;
-import com.jpexs.decompiler.graph.CompilationException;
import java.io.IOException;
public interface As3ScriptReplacerInterface {
public boolean isAvailable();
- public void replaceScript(ScriptPack pack, String text) throws AVM2ParseException, CompilationException, IOException, InterruptedException;
+ public void initReplacement(ScriptPack pack);
+
+ public void replaceScript(ScriptPack pack, String text) throws As3ScriptReplaceException, IOException, InterruptedException;
+
+ public void deinitReplacement(ScriptPack pack);
}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/FFDecAs3ScriptReplacer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/FFDecAs3ScriptReplacer.java
index cf3c2ca9a..723dcdf12 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/FFDecAs3ScriptReplacer.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/FFDecAs3ScriptReplacer.java
@@ -14,53 +14,62 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
-import javax.swing.JOptionPane;
public class FFDecAs3ScriptReplacer implements As3ScriptReplacerInterface {
@Override
- public void replaceScript(ScriptPack pack, String text) throws AVM2ParseException, CompilationException, IOException, InterruptedException {
- ABC abc = pack.abc;
- SWF swf = pack.abc.getSwf();
- String scriptName = pack.getPathScriptName() + ".as";
- int oldIndex = pack.scriptIndex;
- int newIndex = abc.script_info.size();
- String documentClass = swf.getDocumentClass();
- boolean isDocumentClass = documentClass != null && documentClass.equals(pack.getClassPath().toString());
+ public void replaceScript(ScriptPack pack, String text) throws As3ScriptReplaceException, IOException, InterruptedException {
+ try {
+ ABC abc = pack.abc;
+ SWF swf = pack.abc.getSwf();
+ String scriptName = pack.getPathScriptName() + ".as";
+ int oldIndex = pack.scriptIndex;
+ int newIndex = abc.script_info.size();
+ String documentClass = swf.getDocumentClass();
+ boolean isDocumentClass = documentClass != null && documentClass.equals(pack.getClassPath().toString());
- ScriptInfo si = abc.script_info.get(oldIndex);
- if (pack.isSimple) {
- si.delete(abc, true);
- } else {
+ ScriptInfo si = abc.script_info.get(oldIndex);
+ if (pack.isSimple) {
+ si.delete(abc, true);
+ } else {
+ for (int t : pack.traitIndices) {
+ si.traits.traits.get(t).delete(abc, true);
+ }
+ }
+
+ int newClassIndex = abc.instance_info.size();
for (int t : pack.traitIndices) {
- si.traits.traits.get(t).delete(abc, true);
- }
- }
+ if (si.traits.traits.get(t) instanceof TraitClass) {
+ TraitClass tc = (TraitClass) si.traits.traits.get(t);
+ newClassIndex = tc.class_info + 1;
+ }
- int newClassIndex = abc.instance_info.size();
- for (int t : pack.traitIndices) {
- if (si.traits.traits.get(t) instanceof TraitClass) {
- TraitClass tc = (TraitClass) si.traits.traits.get(t);
- newClassIndex = tc.class_info + 1;
+ }
+ List otherAbcs = new ArrayList<>(pack.allABCs);
+
+ otherAbcs.remove(abc);
+
+ ActionScript3Parser.compile(text, abc, otherAbcs, isDocumentClass, scriptName, newClassIndex, oldIndex);
+ if (pack.isSimple) {
+ // Move newly added script to its position
+ abc.script_info.set(oldIndex, abc.script_info.get(newIndex));
+ abc.script_info.remove(newIndex);
+ } else {
+ abc.script_info.get(newIndex).setModified(true);
+ //Note: Is deleting traits safe?
+ List todel = new ArrayList<>(new TreeSet<>(pack.traitIndices));
+ for (int i = todel.size() - 1; i >= 0; i--) {
+ si.traits.traits.remove((int) todel.get(i));
+ }
}
+ abc.script_info.get(oldIndex)
+ .setModified(true);
+ } catch (AVM2ParseException ex) {
+ throw new As3ScriptReplaceException(new As3ScriptReplaceExceptionItem(null, ex.text, (int) ex.line));
+ } catch (CompilationException ex) {
+ throw new As3ScriptReplaceException(new As3ScriptReplaceExceptionItem(null, ex.text, ex.line));
}
- List otherAbcs = new ArrayList<>(pack.allABCs);
- otherAbcs.remove(abc);
- ActionScript3Parser.compile(text, abc, otherAbcs, isDocumentClass, scriptName, newClassIndex, oldIndex);
- if (pack.isSimple) {
- // Move newly added script to its position
- abc.script_info.set(oldIndex, abc.script_info.get(newIndex));
- abc.script_info.remove(newIndex);
- } else {
- abc.script_info.get(newIndex).setModified(true);
- //Note: Is deleting traits safe?
- List todel = new ArrayList<>(new TreeSet<>(pack.traitIndices));
- for (int i = todel.size() - 1; i >= 0; i--) {
- si.traits.traits.remove((int) todel.get(i));
- }
- }
- abc.script_info.get(oldIndex).setModified(true);
}
@Override
@@ -69,4 +78,14 @@ public class FFDecAs3ScriptReplacer implements As3ScriptReplacerInterface {
return !(swc == null || !swc.exists());
}
+ @Override
+ public void initReplacement(ScriptPack pack) {
+ //empty
+ }
+
+ @Override
+ public void deinitReplacement(ScriptPack pack) {
+ //empty
+ }
+
}
diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/flexsdk/As3ScriptReplacerTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/flexsdk/As3ScriptReplacerTest.java
index c966864cd..5b0f32869 100644
--- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/flexsdk/As3ScriptReplacerTest.java
+++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/flexsdk/As3ScriptReplacerTest.java
@@ -3,9 +3,10 @@ package com.jpexs.decompiler.flash.flexsdk;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.configuration.Configuration;
-import com.jpexs.decompiler.flash.exporters.script.LinkReportExporter;
+import com.jpexs.helpers.Helper;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -13,9 +14,10 @@ import org.testng.annotations.Test;
public class As3ScriptReplacerTest {
- @Test
+ //Commented out yet... there's no Flex SDK on build server
+ //@Test
public void testReplace() throws IOException, InterruptedException, Exception {
- MxmlcAs3ScriptReplacer replacer = new MxmlcAs3ScriptReplacer(Configuration.flexSdkLocation.get(), new LinkReportExporter());
+ MxmlcAs3ScriptReplacer replacer = new MxmlcAs3ScriptReplacer(Configuration.flexSdkLocation.get());
SWF swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as3/as3.swf")), false);
String replacement = "package classes\n"
+ "{\n"
diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java
index cc5bbea58..c7a8d6284 100644
--- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java
+++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java
@@ -102,6 +102,8 @@ import com.jpexs.decompiler.flash.helpers.FileTextWriter;
import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
import com.jpexs.decompiler.flash.importers.AS2ScriptImporter;
import com.jpexs.decompiler.flash.importers.AS3ScriptImporter;
+import com.jpexs.decompiler.flash.importers.As3ScriptReplaceException;
+import com.jpexs.decompiler.flash.importers.As3ScriptReplaceExceptionItem;
import com.jpexs.decompiler.flash.importers.As3ScriptReplacerFactory;
import com.jpexs.decompiler.flash.importers.As3ScriptReplacerInterface;
import com.jpexs.decompiler.flash.importers.BinaryDataImporter;
@@ -3581,11 +3583,10 @@ public class CommandLineArgumentParser {
try {
pack.abc.replaceScriptPack(scriptReplacer, pack, as);
- } catch (AVM2ParseException ex) {
- System.err.println("%error% on line %line%".replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)));
- System.exit(1);
- } catch (CompilationException ex) {
- System.err.println("%error% on line %line%".replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)));
+ } catch (As3ScriptReplaceException asre) {
+ for (As3ScriptReplaceExceptionItem item : asre.getExceptionItems()) {
+ logger.log(Level.SEVERE, "%error% on line %line%, column %col%, file: %file%".replace("%error%", item.getMessage()).replace("%line%", Long.toString(item.getLine())).replace("%file%", item.getFile()).replace("%col%", "" + item.getCol()));
+ }
System.exit(1);
}
}
diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java
index 3e9d20a93..411382eb3 100644
--- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java
+++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java
@@ -27,7 +27,6 @@ import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
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.parser.AVM2ParseException;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
import com.jpexs.decompiler.flash.abc.types.ABCException;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
@@ -69,11 +68,12 @@ import com.jpexs.decompiler.flash.gui.abc.tablemodels.UIntTableModel;
import com.jpexs.decompiler.flash.gui.controls.JPersistentSplitPane;
import com.jpexs.decompiler.flash.gui.editor.LinkHandler;
import com.jpexs.decompiler.flash.gui.tagtree.TagTreeModel;
-import com.jpexs.decompiler.flash.importers.As3ScriptReplacerFactory;
+import com.jpexs.decompiler.flash.importers.As3ScriptReplaceException;
+import com.jpexs.decompiler.flash.importers.As3ScriptReplaceExceptionItem;
+import com.jpexs.decompiler.flash.importers.As3ScriptReplacerInterface;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
-import com.jpexs.decompiler.graph.CompilationException;
import com.jpexs.helpers.CancellableWorker;
import com.jpexs.helpers.Helper;
import de.hameister.treetable.MyTreeTable;
@@ -117,6 +117,7 @@ import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.SwingConstants;
+import javax.swing.SwingWorker;
import javax.swing.border.BevelBorder;
import javax.swing.event.EventListenerList;
import javax.swing.event.TableModelListener;
@@ -135,6 +136,9 @@ import jsyntaxpane.TokenType;
*/
public class ABCPanel extends JPanel implements ItemListener, SearchListener, TagEditorPanel {
+ private As3ScriptReplacerInterface scriptReplacer = null;
+ private ScriptPack pack = null;
+
private final MainPanel mainPanel;
public final TraitsList navigator;
@@ -1151,27 +1155,40 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener