Added AS3 Debugging - export/import ByteArray variable data

Fixed Debugging - properly getting variable value through getter
This commit is contained in:
Jindra Petřík
2023-11-11 00:06:22 +01:00
parent 293f6c4a80
commit fcdc94cf02
7 changed files with 118 additions and 28 deletions

View File

@@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.
- Configurable tab size (formatting must be set to use tabs) - default matches indent size of 3
- [#2100] Copy/paste frames (same SWF only)
- Updated portugese-brasil translation
- AS3 Debugging - export/import ByteArray variable data
### Fixed
- [#2021], [#2000] Caret position in editors when using tabs and / or unicode
@@ -17,6 +18,7 @@ All notable changes to this project will be documented in this file.
- [#2122] `-header` command did not support negative integers for displayrect
- AS3 direct editation - namespaces were initialized in class initializers
- Debugging - do not invoke getter when there is none - avoid freezing
- Debugging - properly getting variable value through getter
## [20.0.0] - 2023-11-05

Binary file not shown.

View File

@@ -20,8 +20,11 @@ import com.jpexs.debugger.flash.Variable;
import com.jpexs.debugger.flash.messages.in.InBreakAtExt;
import com.jpexs.debugger.flash.messages.in.InConstantPool;
import com.jpexs.debugger.flash.messages.in.InFrame;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.gui.DebuggerHandler.BreakListener;
import static com.jpexs.decompiler.flash.gui.Main.getDefaultMessagesComponent;
import com.jpexs.decompiler.flash.gui.abc.ABCPanel;
import com.jpexs.helpers.Helper;
import de.hameister.treetable.MyTreeTable;
import de.hameister.treetable.MyTreeTableModel;
import java.awt.BorderLayout;
@@ -31,9 +34,16 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
@@ -161,23 +171,60 @@ public class DebugPanel extends JPanel {
ABCPanel.VariableNode vn;
if (node instanceof ABCPanel.VariableNode) {
vn = ((ABCPanel.VariableNode) node);
v = vn.var;
v = vn.varInsideGetter != null ? vn.varInsideGetter : vn.var;
} else {
return;
}
JPopupMenu pm = new JPopupMenu();
//TODO!!
/*if (v.typeName != null && v.typeName.startsWith("flash.utils::ByteArray")) {
JMenu exportMenu = new JMenu("Export %name%".replace("%name%", v.name));
JMenuItem exportByteArray = new JMenuItem("Export bytearray");
exportByteArray.addActionListener((ActionEvent e1) -> {
Main.dumpBytes(v);
boolean isByteArray = false;
for (Variable t : vn.traits) {
if ("flash.utils::ByteArray".equals(t.name)) {
isByteArray = true;
break;
}
}
if (isByteArray) {
JMenu exportMenu = new JMenu(AppStrings.translate("debug.export").replace("%name%", v.name));
JMenuItem exportByteArrayMenuItem = new JMenuItem(AppStrings.translate("debug.export.bytearray"));
exportByteArrayMenuItem.addActionListener((ActionEvent e1) -> {
JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory(new File(Configuration.lastExportDir.get()));
if (fc.showSaveDialog(Main.getDefaultMessagesComponent()) == JFileChooser.APPROVE_OPTION) {
File file = Helper.fixDialogFile(fc.getSelectedFile());
try (FileOutputStream fos = new FileOutputStream(file)) {
Main.debugExportByteArray(v, fos);
Configuration.lastExportDir.set(file.getParentFile().getAbsolutePath());
} catch (IOException ex) {
Logger.getLogger(DebugPanel.class.getName()).log(Level.SEVERE, null, ex);
ViewMessages.showMessageDialog(getDefaultMessagesComponent(), AppStrings.translate("error.file.save") + ": " + ex.getLocalizedMessage(), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
}
}
});
exportMenu.add(exportByteArray);
exportMenu.add(exportByteArrayMenuItem);
pm.add(exportMenu);
}*/
JMenu importMenu = new JMenu(AppStrings.translate("debug.import").replace("%name%", v.name));
JMenuItem importByteArrayMenuItem = new JMenuItem(AppStrings.translate("debug.import.bytearray"));
importByteArrayMenuItem.addActionListener((ActionEvent e1) -> {
JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get()));
if (fc.showOpenDialog(Main.getDefaultMessagesComponent()) == JFileChooser.APPROVE_OPTION) {
File file = Helper.fixDialogFile(fc.getSelectedFile());
Configuration.lastOpenDir.set(file.getParentFile().getAbsolutePath());
try (FileInputStream fis = new FileInputStream(file)) {
Main.debugImportByteArray(v, fis);
} catch (IOException ex) {
Logger.getLogger(DebugPanel.class.getName()).log(Level.SEVERE, null, ex);
ViewMessages.showMessageDialog(getDefaultMessagesComponent(), AppStrings.translate("error.file.save") + ": " + ex.getLocalizedMessage(), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
}
}
});
importMenu.add(importByteArrayMenuItem);
pm.add(importMenu);
}
long watchParentId = vn.parentObjectId;
JMenu addWatchMenu = new JMenu(AppStrings.translate("debug.watch.add").replace("%name%", v.name));

View File

@@ -291,25 +291,50 @@ public class Main {
return runProcess != null && !runProcessDebug;
}
/*
* FIXME!
*/
public static synchronized void dumpBytes(Variable v) {
InCallFunction icf;
public static synchronized void debugExportByteArray(Variable v, OutputStream os) throws IOException {
try {
long objectId = 0L;
if ((v.vType == VariableType.OBJECT || v.vType == VariableType.MOVIECLIP)) {
objectId = (Long) v.value;
}
Object oldPos = getDebugHandler().getVariable(objectId, "position", true, true).parent.value;
Object oldPos = getDebugHandler().getVariable(objectId, "position", false, true).parent.value;
getDebugHandler().setVariable(objectId, "position", VariableType.NUMBER, 0);
icf = getDebugHandler().callFunction(false, "readUTF", v, new ArrayList<>());
System.out.println("Result=" + icf.variables.get(0).value);
int length = (int)(double)(Double)getDebugHandler().getVariable(objectId, "length", false, true).parent.value;
for (int i = 0; i < length; i++) {
int b = (int)(double)(Double)getDebugHandler().callFunction(false, "readByte", v, new ArrayList<>()).variables.get(0).value;
os.write(b);
}
getDebugHandler().setVariable(objectId, "position", VariableType.NUMBER, oldPos);
} catch (DebuggerHandler.ActionScriptException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static synchronized void debugImportByteArray(Variable v, InputStream is) throws IOException {
try {
long objectId = 0L;
if ((v.vType == VariableType.OBJECT || v.vType == VariableType.MOVIECLIP)) {
objectId = (Long) v.value;
}
Double oldPos = (Double) getDebugHandler().getVariable(objectId, "position", false, true).parent.value;
getDebugHandler().setVariable(objectId, "length", VariableType.NUMBER, 0);
getDebugHandler().setVariable(objectId, "position", VariableType.NUMBER, 0);
int length = 0;
int b;
while ((b = is.read()) > -1) {
getDebugHandler().callFunction(false, "writeByte", v, Arrays.asList((Double)(double) b));
length++;
}
if (oldPos > length) {
oldPos = (Double) (double) length;
}
getDebugHandler().setVariable(objectId, "position", VariableType.NUMBER, oldPos);
} catch (DebuggerHandler.ActionScriptException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static synchronized boolean addWatch(Variable v, long v_id, boolean watchRead, boolean watchWrite) {

View File

@@ -289,6 +289,8 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
public long traitId;
private List<VariableNode> childs;
public List<Variable> traits = new ArrayList<>();
@Override
public int hashCode() {
@@ -347,17 +349,18 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
private void reloadChildren() {
childs = new ArrayList<>();
traits = new ArrayList<>();
if ("".equals(var.name)) {
return;
}
InGetVariable igv;
Long objectId = varToObjectId(varInsideGetter);
Long objectId = varToObjectId(var);
boolean useGetter = (var.flags & VariableFlags.HAS_GETTER) > 0;
if (parentObjectId == 0 && objectId != 0) {
boolean useGetter = (var.flags & VariableFlags.IS_CONST) == 0;
if (objectId != 0) {
igv = Main.getDebugHandler().getVariable(objectId, "", true, useGetter);
} else {
igv = Main.getDebugHandler().getVariable(parentObjectId, var.name, true, useGetter);
@@ -371,10 +374,11 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
Variable curTrait = null;
for (int i = 0; i < igv.childs.size(); i++) {
if (!isTraits(igv.childs.get(i))) {
Long parentObjectId = varToObjectId(var);
Long parentObjectId = varToObjectId(varInsideGetter);
childs.add(new VariableNode(path, level + 1, igv.childs.get(i), parentObjectId, curTrait));
} else {
curTrait = igv.childs.get(i);
traits.add(curTrait);
}
}
}
@@ -427,11 +431,13 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
}
public static Long varToObjectId(Variable var) {
if (var != null && (var.vType == VariableType.OBJECT)) {
return (Long) var.value;
} else {
if (var == null) {
return 0L;
}
if (var.vType == VariableType.OBJECT) {
return (Long) var.value;
}
return 0L;
}
public static class VariablesTableModel implements MyTreeTableModel {

View File

@@ -1229,4 +1229,9 @@ contextmenu.moveFrame = Move frame to
contextmenu.clipboard.frame = Frame clipboard
clipboard.hint.frame = Number of items in the frame clipboard
clipboard.clear.frame = Clear the frame clipboard
clipboard.clear.frame = Clear the frame clipboard
debug.export = Export %name%
debug.export.bytearray = Export byte array data...
debug.import = Import to %name%
debug.import.bytearray = Import byte array data...

View File

@@ -1206,4 +1206,9 @@ contextmenu.moveFrame = P\u0159esunout sn\u00edmek do
contextmenu.clipboard.frame = Sn\u00edmkov\u00e1 schr\u00e1nka
clipboard.hint.frame = Po\u010det polo\u017eek ve sn\u00edmkov\u00e9 schr\u00e1nce
clipboard.clear.frame = Vy\u010distit sn\u00edmkovou schr\u00e1nku
clipboard.clear.frame = Vy\u010distit sn\u00edmkovou schr\u00e1nku
debug.export = Exportovat %name%
debug.export.bytearray = Exportovat byte array data...
debug.import = Importovat do %name%
debug.import.bytearray = Importovat byte array data...