Switch to line info extraction through single top script processing

This commit is contained in:
igor%mir2.org 2004-05-22 23:19:56 +00:00
Родитель bca4ff3ba4
Коммит 30e9aee832
3 изменённых файлов: 515 добавлений и 412 удалений

Просмотреть файл

@ -45,15 +45,18 @@ import java.awt.*;
import java.awt.event.*;
import java.util.StringTokenizer;
import org.mozilla.javascript.*;
import org.mozilla.javascript.debug.*;
import org.mozilla.javascript.tools.shell.ConsoleTextArea;
import java.util.*;
import java.io.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import java.lang.reflect.Method;
import java.net.URL;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.Kit;
import org.mozilla.javascript.tools.shell.ConsoleTextArea;
class MessageDialogWrapper {
@ -353,8 +356,6 @@ class FilePopupMenu extends JPopupMenu {
item.addActionListener(w);
add(item = new JMenuItem("Clear Breakpoint"));
item.addActionListener(w);
//add(item = new JMenuItem("Run to Cursor"));
//item.addActionListener(w);
add(item = new JMenuItem("Run"));
item.addActionListener(w);
}
@ -459,8 +460,6 @@ class FileTextArea extends JTextArea implements ActionListener,
w.setBreakPoint(line + 1);
} else if (cmd.equals("Clear Breakpoint")) {
w.clearBreakPoint(line + 1);
} else if (cmd.equals("Run to Cursor")) {
w.runToCursor(e);
} else if (cmd.equals("Run")) {
w.load();
}
@ -608,7 +607,6 @@ class MoreWindows extends JDialog implements ActionListener {
class FindFunction extends JDialog implements ActionListener {
private String value = null;
private JList list;
Hashtable functionNames;
DebugGui debugGui;
JButton setButton;
JButton refreshButton;
@ -641,11 +639,11 @@ class FindFunction extends JDialog implements ActionListener {
return;
}
setVisible(false);
Main.ScriptItem item = (Main.ScriptItem)functionNames.get(value);
Main.FunctionSource item = debugGui.main.functionSourceByName(value);
if (item != null) {
Main.SourceInfo si = item.getSourceInfo();
String url = si.getUrl();
int lineNumber = item.getFirstLine();
Main.SourceInfo si = item.sourceInfo();
String url = si.url();
int lineNumber = item.firstLine();
FileWindow w = debugGui.getFileWindow(url);
if (w == null) {
debugGui.createFileWindow(si, lineNumber);
@ -676,11 +674,9 @@ class FindFunction extends JDialog implements ActionListener {
}
};
FindFunction(DebugGui debugGui, Hashtable functionNames,
String title,
String labelText) {
FindFunction(DebugGui debugGui, String title, String labelText)
{
super(debugGui, title, true);
this.functionNames = functionNames;
this.debugGui = debugGui;
cancelButton = new JButton("Cancel");
@ -693,14 +689,9 @@ class FindFunction extends JDialog implements ActionListener {
DefaultListModel model = (DefaultListModel)list.getModel();
model.clear();
Enumeration e = functionNames.keys();
String[] a = new String[functionNames.size()];
int i = 0;
while (e.hasMoreElements()) {
a[i++] = e.nextElement().toString();
}
String[] a = debugGui.main.functionNames();
java.util.Arrays.sort(a);
for (i = 0; i < a.length; i++) {
for (int i = 0; i < a.length; i++) {
model.addElement(a[i]);
}
list.setSelectedIndex(0);
@ -900,24 +891,10 @@ class FileWindow extends JInternalFrame implements ActionListener {
}
}
void runToCursor(ActionEvent e) {
try {
debugGui.runToCursor(getUrl(),
textArea.getLineOfOffset(textArea.getCaretPosition()) + 1,
e);
} catch (BadLocationException exc) {
}
}
void load() {
Scriptable scope = debugGui.main.getScope();
if (scope == null) {
MessageDialogWrapper.showMessageDialog(debugGui, "Can't load scripts: no scope available", "Run", JOptionPane.ERROR_MESSAGE);
} else {
String url = getUrl();
if (url != null) {
new Thread(new LoadFile(debugGui,scope,url)).start();
}
String url = getUrl();
if (url != null) {
new Thread(new LoadFile(debugGui,url,sourceInfo.source())).start();
}
}
@ -931,7 +908,7 @@ class FileWindow extends JInternalFrame implements ActionListener {
}
boolean isBreakPoint(int line) {
return sourceInfo.hasBreakpoint(line);
return sourceInfo.breakableLine(line) && sourceInfo.breakpoint(line);
}
void toggleBreakPoint(int line) {
@ -943,19 +920,25 @@ class FileWindow extends JInternalFrame implements ActionListener {
}
void setBreakPoint(int line) {
if (sourceInfo.placeBreakpoint(line)) {
fileHeader.repaint();
if (sourceInfo.breakableLine(line)) {
boolean changed = sourceInfo.breakpoint(line, true);
if (changed) {
fileHeader.repaint();
}
}
}
void clearBreakPoint(int line) {
if (sourceInfo.removeBreakpoint(line)) {
fileHeader.repaint();
if (sourceInfo.breakableLine(line)) {
boolean changed = sourceInfo.breakpoint(line, false);
if (changed) {
fileHeader.repaint();
}
}
}
FileWindow(DebugGui debugGui, Main.SourceInfo sourceInfo) {
super(Main.SourceInfo.getShortName(sourceInfo.getUrl()),
super(DebugGui.getShortName(sourceInfo.url()),
true, true, true, true);
this.debugGui = debugGui;
this.sourceInfo = sourceInfo;
@ -970,7 +953,7 @@ class FileWindow extends JInternalFrame implements ActionListener {
p.setRowHeaderView(fileHeader);
setContentPane(p);
pack();
updateText();
updateText(sourceInfo);
textArea.select(0);
}
@ -984,11 +967,12 @@ class FileWindow extends JInternalFrame implements ActionListener {
}
public String getUrl() {
return sourceInfo.getUrl();
return sourceInfo.url();
}
void updateText() {
String newText = sourceInfo.getSource();
void updateText(Main.SourceInfo sourceInfo) {
this.sourceInfo = sourceInfo;
String newText = sourceInfo.source();
if (!textArea.getText().equals(newText)) {
textArea.setText(newText);
int pos = 0;
@ -1737,7 +1721,7 @@ class Menubar extends JMenuBar implements ActionListener
count--;
windowMenu.remove(lastItem);
}
String shortName = Main.SourceInfo.getShortName(url);
String shortName = DebugGui.getShortName(url);
windowMenu.add(item = new JMenuItem((char)('0' + (count-4)) + " " + shortName, '0' + (count - 4)));
if (hasMoreWin) {
@ -1754,63 +1738,49 @@ class Menubar extends JMenuBar implements ActionListener
class OpenFile implements Runnable
{
String fileName;
DebugGui debugGui;
OpenFile(DebugGui debugGui, String fileName)
String fileName;
String text;
OpenFile(DebugGui debugGui, String fileName, String text)
{
this.fileName = fileName;
this.debugGui = debugGui;
this.fileName = fileName;
this.text = text;
}
public void run() {
Context cx = Context.enter();
ContextData contextData = ContextData.get(cx);
contextData.breakNextLine = true;
try {
cx.compileReader(new FileReader(fileName), fileName, 1, null);
} catch (Exception exc) {
String msg = exc.getMessage();
if (exc instanceof EcmaError) {
EcmaError err = (EcmaError)exc;
msg = err.getSourceName() + ", line " + err.getLineNumber() + ": " + msg;
}
debugGui.main.compileScript(fileName, text);
} catch (RuntimeException ex) {
MessageDialogWrapper.showMessageDialog(debugGui,
msg,
"Error Compiling File",
ex.getMessage(),
"Error Compiling "+fileName,
JOptionPane.ERROR_MESSAGE);
} finally {
cx.exit();
}
}
}
class LoadFile implements Runnable {
Scriptable scope;
String fileName;
class LoadFile implements Runnable
{
DebugGui debugGui;
LoadFile(DebugGui debugGui, Scriptable scope, String fileName) {
this.scope = scope;
this.fileName = fileName;
String fileName;
String text;
LoadFile(DebugGui debugGui, String fileName, String text)
{
this.debugGui = debugGui;
this.fileName = fileName;
this.text = text;
}
public void run() {
Context cx = Context.enter();
ContextData contextData = ContextData.get(cx);
contextData.breakNextLine = true;
public void run()
{
try {
cx.evaluateReader(scope, new FileReader(fileName),
fileName, 1, null);
} catch (Exception exc) {
String msg = exc.getMessage();
if (exc instanceof EcmaError) {
EcmaError err = (EcmaError)exc;
msg = err.getSourceName() + ", line " + err.getLineNumber() + ": " + msg;
}
debugGui.main.evalScript(fileName, text);
} catch (RuntimeException ex) {
MessageDialogWrapper.showMessageDialog(debugGui,
msg,
"Run",
ex.getMessage(),
"Run error for "+fileName,
JOptionPane.ERROR_MESSAGE);
} finally {
cx.exit();
}
}
}
@ -1993,12 +1963,24 @@ class DebugGui extends JFrame
return (FileWindow)fileWindows.get(url);
}
static String getShortName(String url) {
int lastSlash = url.lastIndexOf('/');
if (lastSlash < 0) {
lastSlash = url.lastIndexOf('\\');
}
String shortName = url;
if (lastSlash >= 0 && lastSlash + 1 < url.length()) {
shortName = url.substring(lastSlash + 1);
}
return shortName;
}
void removeWindow(FileWindow w) {
fileWindows.remove(w.getUrl());
JMenu windowMenu = getWindowMenu();
int count = windowMenu.getItemCount();
JMenuItem lastItem = windowMenu.getItem(count -1);
String name = Main.SourceInfo.getShortName(w.getUrl());
String name = getShortName(w.getUrl());
for (int i = 5; i < count; i++) {
JMenuItem item = windowMenu.getItem(i);
if (item == null) continue; // separator
@ -2070,7 +2052,7 @@ class DebugGui extends JFrame
{
boolean activate = true;
String url = sourceInfo.getUrl();
String url = sourceInfo.url();
FileWindow w = new FileWindow(this, sourceInfo);
fileWindows.put(url, w);
if (line != -1) {
@ -2141,10 +2123,10 @@ class DebugGui extends JFrame
public void updateFileText(Main.SourceInfo sourceInfo)
{
String fileName = sourceInfo.getUrl();
String fileName = sourceInfo.url();
FileWindow w = getFileWindow(fileName);
if (w != null) {
w.updateText();
w.updateText(sourceInfo);
w.show();
} else if (!fileName.equals("<stdin>")) {
createFileWindow(sourceInfo, -1);
@ -2213,20 +2195,6 @@ class DebugGui extends JFrame
ctx.setMinimumSize(new Dimension(50, ctx.getMinimumSize().height));
}
void runToCursor(String fileName,
int lineNumber,
ActionEvent evt) {
Main.SourceInfo si = (Main.SourceInfo)main.sourceNames.get(fileName);
if (si == null) {
System.out.println("debugger error: Couldn't find source: " + fileName);
}
if (si.breakableLine(lineNumber)) {
main.runToCursorFile = fileName;
main.runToCursorLine = lineNumber;
actionPerformed(evt);
}
}
JMenu getWindowMenu() {
return menubar.getMenu(3);
}
@ -2285,24 +2253,22 @@ class DebugGui extends JFrame
returnValue = Main.GO;
} else if (cmd.equals("Break")) {
main.doBreak();
} else if (cmd.equals("Run to Cursor")) {
returnValue = Main.RUN_TO_CURSOR;
} else if (cmd.equals("Exit")) {
main.Exit();
} else if (cmd.equals("Open")) {
String fileName = chooseFile("Select a file to compile");
if (fileName != null) {
new Thread(new OpenFile(this, fileName)).start();
String text = readFile(fileName);
if (text != null) {
new Thread(new OpenFile(this, fileName, text)).start();
}
}
} else if (cmd.equals("Load")) {
Scriptable scope = main.getScope();
if (scope == null) {
MessageDialogWrapper.showMessageDialog(this, "Can't run scripts: no scope available", "Run", JOptionPane.ERROR_MESSAGE);
} else {
String fileName = chooseFile("Select a file to execute");
if (fileName != null) {
new Thread(new LoadFile(this, scope,
fileName)).start();
String fileName = chooseFile("Select a file to execute");
if (fileName != null) {
String text = readFile(fileName);
if (text != null) {
new Thread(new LoadFile(this, fileName, text)).start();
}
}
} else if (cmd.equals("More Windows...")) {
@ -2320,8 +2286,7 @@ class DebugGui extends JFrame
} else if (cmd.equals("Copy")) {
} else if (cmd.equals("Paste")) {
} else if (cmd.equals("Go to function...")) {
FindFunction dlg = new FindFunction(this, main.functionNames,
"Go to function",
FindFunction dlg = new FindFunction(this, "Go to function",
"Function");
dlg.showDialog(this);
} else if (cmd.equals("Tile")) {
@ -2433,5 +2398,25 @@ class DebugGui extends JFrame
}
}
String readFile(String fileName)
{
String text;
try {
Reader r = new FileReader(fileName);
try {
text = Kit.readReader(r);
} finally {
r.close();
}
} catch (IOException ex) {
MessageDialogWrapper.showMessageDialog(this,
ex.getMessage(),
"Error reading "+fileName,
JOptionPane.ERROR_MESSAGE);
text = null;
}
return text;
}
}

Просмотреть файл

@ -55,7 +55,7 @@ import javax.swing.tree.DefaultTreeCellRenderer;
import java.lang.reflect.Method;
import java.net.URL;
public class Main implements Debugger, ContextListener {
public class Main {
DebugGui debugGui;
@ -64,8 +64,7 @@ public class Main implements Debugger, ContextListener {
static final int STEP_OUT = 2;
static final int GO = 3;
static final int BREAK = 4;
static final int RUN_TO_CURSOR = 5;
static final int EXIT = 6;
static final int EXIT = 5;
static class ContextData
{
@ -103,10 +102,10 @@ public class Main implements Debugger, ContextListener {
this.db = db;
this.contextData = ContextData.get(cx);
this.fnOrScript = fnOrScript;
ScriptItem item = db.getScriptItem(fnOrScript);
FunctionSource item = db.getFunctionSource(fnOrScript);
if (item != null) {
this.sourceInfo = item.getSourceInfo();
this.lineNumber = item.getFirstLine();
this.sourceInfo = item.sourceInfo();
this.lineNumber = item.firstLine();
}
contextData.pushFrame(this);
}
@ -125,7 +124,7 @@ public class Main implements Debugger, ContextListener {
this.lineNumber = lineno;
checks:
if (sourceInfo == null || !sourceInfo.hasBreakpoint(lineno)) {
if (sourceInfo == null || !sourceInfo.checkBreakpointFast(lineno)) {
if (db.breakFlag) {
break checks;
}
@ -175,7 +174,7 @@ public class Main implements Debugger, ContextListener {
String getUrl() {
if (sourceInfo != null) {
return sourceInfo.getUrl();
return sourceInfo.url();
}
return db.getNormilizedUrl(fnOrScript);
}
@ -197,184 +196,222 @@ public class Main implements Debugger, ContextListener {
private int lineNumber;
}
static class ScriptItem {
ScriptItem(DebuggableScript fnOrScript, SourceInfo sourceInfo) {
this.fnOrScript = fnOrScript;
this.sourceInfo = sourceInfo;
}
DebuggableScript getScript() { return fnOrScript; }
SourceInfo getSourceInfo() { return sourceInfo; }
int getFirstLine() {
return (firstLine == 0) ? 1 : firstLine;
}
void setFirstLine(int firstLine) {
if (firstLine <= 0) { throw new IllegalArgumentException(); }
if (this.firstLine != 0) { throw new IllegalStateException(); }
this.firstLine = firstLine;
}
private DebuggableScript fnOrScript;
static class FunctionSource
{
private SourceInfo sourceInfo;
private int firstLine;
private String name;
FunctionSource(SourceInfo sourceInfo, int firstLine, String name)
{
if (name == null) throw new IllegalArgumentException();
this.sourceInfo = sourceInfo;
this.firstLine = firstLine;
this.name = name;
}
SourceInfo sourceInfo()
{
return sourceInfo;
}
int firstLine()
{
return firstLine;
}
String name()
{
return name;
}
}
static class SourceInfo {
static class SourceInfo
{
private String source;
private String url;
static String getShortName(String url) {
int lastSlash = url.lastIndexOf('/');
if (lastSlash < 0) {
lastSlash = url.lastIndexOf('\\');
}
String shortName = url;
if (lastSlash >= 0 && lastSlash + 1 < url.length()) {
shortName = url.substring(lastSlash + 1);
}
return shortName;
}
private int minLine;
private boolean[] breakableLines;
private boolean[] breakpoints;
SourceInfo(String sourceUrl, String source) {
this.sourceUrl = sourceUrl;
private static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];
private FunctionSource[] functionSources;
SourceInfo(String source, DebuggableScript[] functions,
String normilizedUrl)
{
this.source = source;
}
this.url = normilizedUrl;
String getUrl() {
return sourceUrl;
}
int N = functions.length;
int[][] lineArrays = new int[N][];
for (int i = 0; i != N; ++i) {
lineArrays[i] = functions[i].getLineNumbers();
}
String getSource() {
return source;
}
synchronized void setSource(String source) {
if (!this.source.equals(source)) {
this.source = source;
endLine = 0;
breakableLines = null;
if (breakpoints != null) {
for (int i = breakpoints.length - 1; i >= 0; --i) {
if (breakpoints[i] == BREAK_FLAG) {
breakpoints[i] = OLD_BREAK_FLAG;
int minAll = 0, maxAll = -1;
int[] firstLines = new int[N];
for (int i = 0; i != N; ++i) {
int[] lines = lineArrays[i];
if (lines == null || lines.length == 0) {
firstLines[i] = -1;
} else {
int min, max;
min = max = lines[0];
for (int j = 1; j != lines.length; ++j) {
int line = lines[j];
if (line < min) {
min = line;
} else if (line > max) {
max = line;
}
}
firstLines[i] = min;
if (minAll > maxAll) {
minAll = min;
maxAll = max;
} else {
if (min < minAll) {
minAll = min;
}
if (max > maxAll) {
maxAll = max;
}
}
}
}
}
synchronized void updateLineInfo(ScriptItem item) {
int[] lines = item.getScript().getLineNumbers();
if (lines.length == 0) {
return;
}
int fnFirstLine = lines[0];
int fnEndLine = fnFirstLine + 1;
for (int i = 1; i != lines.length; ++i) {
int line = lines[i];
if (line < fnFirstLine) {
fnFirstLine = line;
}else if (line >= fnEndLine) {
fnEndLine = line + 1;
if (minAll > maxAll) {
// No line information
this.minLine = -1;
this.breakableLines = EMPTY_BOOLEAN_ARRAY;
this.breakpoints = EMPTY_BOOLEAN_ARRAY;
} else {
if (minAll < 0) {
// Line numbers can not be negative
throw new IllegalStateException(String.valueOf(minAll));
}
}
item.setFirstLine(fnFirstLine);
if (endLine < fnEndLine) {
endLine = fnEndLine;
}
if (breakableLines == null) {
int newLength = 20;
if (newLength < endLine) { newLength = endLine; }
breakableLines = new boolean[newLength];
}else if (breakableLines.length < endLine) {
int newLength = breakableLines.length * 2;
if (newLength < endLine) { newLength = endLine; }
boolean[] tmp = new boolean[newLength];
System.arraycopy(breakableLines, 0, tmp, 0, breakableLines.length);
breakableLines = tmp;
}
int breakpointsEnd = (breakpoints == null) ? 0 : breakpoints.length;
for (int i = 0; i != lines.length; ++i) {
int line = lines[i];
breakableLines[line] = true;
if (line < breakpointsEnd) {
if (breakpoints[line] == OLD_BREAK_FLAG) {
breakpoints[line] = BREAK_FLAG;
this.minLine = minAll;
int linesTop = maxAll + 1;
this.breakableLines = new boolean[linesTop];
this.breakpoints = new boolean[linesTop];
for (int i = 0; i != N; ++i) {
int[] lines = lineArrays[i];
if (lines != null && lines.length != 0) {
for (int j = 0; j != lines.length; ++j) {
int line = lines[j];
this.breakableLines[line] = true;
}
}
}
}
}
boolean breakableLine(int line) {
boolean[] breakableLines = this.breakableLines;
if (breakableLines != null && line < breakableLines.length) {
return breakableLines[line];
}
return false;
}
boolean hasBreakpoint(int line) {
byte[] breakpoints = this.breakpoints;
if (breakpoints != null && line < breakpoints.length) {
return breakpoints[line] == BREAK_FLAG;
}
return false;
}
synchronized boolean placeBreakpoint(int line) {
if (breakableLine(line)) {
if (breakpoints == null) {
breakpoints = new byte[endLine];
}else if (line >= breakpoints.length) {
byte[] tmp = new byte[endLine];
System.arraycopy(breakpoints, 0, tmp, 0, breakpoints.length);
breakpoints = tmp;
this.functionSources = new FunctionSource[N];
for (int i = 0; i != N; ++i) {
String name = functions[i].getFunctionName();
if (name == null) {
name = "";
}
breakpoints[line] = BREAK_FLAG;
return true;
this.functionSources[i]
= new FunctionSource(this, firstLines[i], name);
}
return false;
}
synchronized boolean removeBreakpoint(int line) {
boolean wasBreakpoint = false;
if (breakpoints != null && line < breakpoints.length) {
wasBreakpoint = (breakpoints[line] == BREAK_FLAG);
breakpoints[line] = 0;
String source()
{
return this.source;
}
String url()
{
return this.url;
}
int functionSourcesTop()
{
return functionSources.length;
}
FunctionSource functionSource(int i)
{
return functionSources[i];
}
void copyBreakpointsFrom(SourceInfo old)
{
int end = old.breakpoints.length;
if (end > this.breakpoints.length) {
end = this.breakpoints.length;
}
for (int line = 0; line != end; ++line) {
if (old.breakpoints[line]) {
this.breakpoints[line] = true;
}
}
return wasBreakpoint;
}
synchronized void removeAllBreakpoints() {
breakpoints = null;
boolean breakableLine(int line)
{
return (line < this.breakableLines.length)
&& this.breakableLines[line];
}
private String sourceUrl;
private String source;
boolean breakpoint(int line)
{
if (!breakableLine(line)) {
throw new IllegalArgumentException(String.valueOf(line));
}
return line < this.breakpoints.length && this.breakpoints[line];
}
private int endLine;
private boolean[] breakableLines;
final boolean checkBreakpointFast(int line)
{
return this.breakpoints[line];
}
private static final byte BREAK_FLAG = 1;
private static final byte OLD_BREAK_FLAG = 2;
private byte[] breakpoints;
boolean breakpoint(int line, boolean value)
{
if (!breakableLine(line)) {
throw new IllegalArgumentException(String.valueOf(line));
}
boolean changed;
synchronized (breakpoints) {
if (breakpoints[line] != value) {
breakpoints[line] = value;
changed = true;
} else {
changed = false;
}
}
return changed;
}
void removeAllBreakpoints()
{
synchronized (breakpoints) {
for (int line = 0; line != breakpoints.length; ++line) {
breakpoints[line] = false;
}
}
}
}
private final Debugger debuggerImpl = new Debugger()
{
public DebugFrame getFrame(Context cx, DebuggableScript fnOrScript)
{
return mirrorStackFrame(cx, fnOrScript);
}
public void handleCompilationDone(Context cx,
DebuggableScript fnOrScript,
String source)
{
onCompilationDone(cx, fnOrScript, source);
}
};
int runToCursorLine;
String runToCursorFile;
private Hashtable scriptItems = new Hashtable();
Hashtable sourceNames = new Hashtable();
Hashtable functionNames = new Hashtable();
boolean breakFlag = false;
@ -400,80 +437,209 @@ public class Main implements Debugger, ContextListener {
boolean breakOnEnter;
boolean breakOnReturn;
private final Hashtable urlToSourceInfo = new Hashtable();
private final Hashtable functionNames = new Hashtable();
private final Hashtable functionToSource = new Hashtable();
/* ContextListener interface */
void enableForAllNewContexts()
{
Context.addContextListener(new ContextListener() {
public void contextCreated(Context cx) {
public void contextCreated(Context cx)
{
initNewContext(cx);
}
public void contextEntered(Context cx) { }
public void contextExited(Context cx) { }
public void contextReleased(Context cx) { }
});
}
void initNewContext(Context cx)
{
ContextData contextData = new ContextData();
cx.setDebugger(this, contextData);
cx.setDebugger(debuggerImpl, contextData);
cx.setGeneratingDebug(true);
cx.setOptimizationLevel(-1);
}
public void contextEntered(Context cx) {
DebugFrame mirrorStackFrame(Context cx, DebuggableScript fnOrScript)
{
return new StackFrame(cx, this, fnOrScript);
}
public void contextExited(Context cx) {
void onCompilationDone(Context cx, DebuggableScript fnOrScript,
String source)
{
if (!fnOrScript.isTopLevel()) {
return;
}
registerTopScript(fnOrScript, source);
}
public void contextReleased(Context cx) {
}
/* end ContextListener interface */
public void doBreak() {
breakFlag = true;
}
ScriptItem getScriptItem(DebuggableScript fnOrScript) {
ScriptItem item = (ScriptItem)scriptItems.get(fnOrScript);
if (item == null) {
FunctionSource getFunctionSource(DebuggableScript fnOrScript)
{
FunctionSource fsource = functionSource(fnOrScript);
if (fsource == null) {
String url = getNormilizedUrl(fnOrScript);
SourceInfo si = (SourceInfo)sourceNames.get(url);
SourceInfo si = sourceInfo(url);
if (si == null) {
if (!fnOrScript.isGeneratedScript()) {
// Not eval or Function, try to load it from URL
String source = null;
try {
InputStream is = openSource(url);
try {
source = Kit.readReader(new InputStreamReader(is));
} finally {
is.close();
}
} catch (IOException ex) {
System.err.println
("Failed to load source from "+url+": "+ ex);
}
String source = loadSource(url);
if (source != null) {
si = registerSource(url, source);
DebuggableScript top = fnOrScript;
for (;;) {
DebuggableScript parent = top.getParent();
if (parent == null) {
break;
}
top = parent;
}
registerTopScript(top, source);
fsource = functionSource(fnOrScript);
}
}
}
if (si != null) {
item = registerScript(si, fnOrScript);
}
return fsource;
}
private String loadSource(String sourceUrl)
{
String source = null;
int hash = sourceUrl.indexOf('#');
if (hash >= 0) {
sourceUrl = sourceUrl.substring(0, hash);
}
try {
InputStream is;
openStream:
{
if (sourceUrl.indexOf(':') < 0) {
// Can be a file name
try {
if (sourceUrl.startsWith("~/")) {
String home = System.getProperty("user.home");
if (home != null) {
String pathFromHome = sourceUrl.substring(2);
File f = new File(new File(home), pathFromHome);
if (f.exists()) {
is = new FileInputStream(f);
break openStream;
}
}
}
File f = new File(sourceUrl);
if (f.exists()) {
is = new FileInputStream(f);
break openStream;
}
} catch (SecurityException ex) { }
// No existing file, assume missed http://
if (sourceUrl.startsWith("//")) {
sourceUrl = "http:" + sourceUrl;
} else if (sourceUrl.startsWith("/")) {
sourceUrl = "http://127.0.0.1" + sourceUrl;
} else {
sourceUrl = "http://" + sourceUrl;
}
}
is = (new java.net.URL(sourceUrl)).openStream();
}
try {
source = Kit.readReader(new InputStreamReader(is));
} finally {
is.close();
}
} catch (IOException ex) {
System.err.println
("Failed to load source from "+sourceUrl+": "+ ex);
}
return source;
}
private void registerTopScript(DebuggableScript topScript, String source)
{
if (!topScript.isTopLevel()) {
throw new IllegalArgumentException();
}
String url = getNormilizedUrl(topScript);
DebuggableScript[] functions = getAllFunctions(topScript);
final SourceInfo sourceInfo = new SourceInfo(source, functions, url);
synchronized (urlToSourceInfo) {
SourceInfo old = (SourceInfo)urlToSourceInfo.get(url);
if (old != null) {
sourceInfo.copyBreakpointsFrom(old);
}
urlToSourceInfo.put(url, sourceInfo);
for (int i = 0; i != sourceInfo.functionSourcesTop(); ++i) {
FunctionSource fsource = sourceInfo.functionSource(i);
String name = fsource.name();
if (name.length() != 0) {
functionNames.put(name, fsource);
}
}
}
return item;
synchronized (functionToSource) {
for (int i = 0; i != functions.length; ++i) {
FunctionSource fsource = sourceInfo.functionSource(i);
functionToSource.put(functions[i], fsource);
}
}
swingInvokeLater(new Runnable() {
public void run()
{
debugGui.updateFileText(sourceInfo);
}
});
}
/* Debugger Interface */
public void handleCompilationDone(Context cx, DebuggableScript fnOrScript,
String source)
FunctionSource functionSource(DebuggableScript fnOrScript)
{
String sourceUrl = getNormilizedUrl(fnOrScript);
SourceInfo si = registerSource(sourceUrl, source);
registerScript(si, fnOrScript);
return (FunctionSource)functionToSource.get(fnOrScript);
}
String getNormilizedUrl(DebuggableScript fnOrScript) {
String[] functionNames()
{
String[] a;
synchronized (urlToSourceInfo) {
Enumeration e = functionNames.keys();
a = new String[functionNames.size()];
int i = 0;
while (e.hasMoreElements()) {
a[i++] = (String)e.nextElement();
}
}
return a;
}
FunctionSource functionSourceByName(String functionName)
{
return (FunctionSource)functionNames.get(functionName);
}
SourceInfo sourceInfo(String url)
{
return (SourceInfo)urlToSourceInfo.get(url);
}
String getNormilizedUrl(DebuggableScript fnOrScript)
{
String url = fnOrScript.getSourceName();
if (url == null) { url = "<stdin>"; }
else {
// Not to produce window for eval from different lines,
// strip line numbers, i.e. replace all #[0-9]+\(eval\) by (eval)
// strip line numbers, i.e. replace all #[0-9]+\(eval\) by
// (eval)
// Option: similar teatment for Function?
char evalSeparator = '#';
StringBuffer sb = null;
@ -520,78 +686,26 @@ public class Main implements Debugger, ContextListener {
return url;
}
private static InputStream openSource(String sourceUrl)
throws IOException
private static DebuggableScript[] getAllFunctions(DebuggableScript function)
{
int hash = sourceUrl.indexOf('#');
if (hash >= 0) {
sourceUrl = sourceUrl.substring(0, hash);
}
if (sourceUrl.indexOf(':') < 0) {
// Can be a file name
try {
if (sourceUrl.startsWith("~/")) {
String home = System.getProperty("user.home");
if (home != null) {
String pathFromHome = sourceUrl.substring(2);
File f = new File(new File(home), pathFromHome);
if (f.exists()) {
return new FileInputStream(f);
}
}
}
File f = new File(sourceUrl);
if (f.exists()) {
return new FileInputStream(f);
}
} catch (SecurityException ex) { }
// No existing file, assume missed http://
if (sourceUrl.startsWith("//")) {
sourceUrl = "http:" + sourceUrl;
} else if (sourceUrl.startsWith("/")) {
sourceUrl = "http://127.0.0.1" + sourceUrl;
} else {
sourceUrl = "http://" + sourceUrl;
}
}
return (new java.net.URL(sourceUrl)).openStream();
ObjArray functions = new ObjArray();
collectFunctions_r(function, functions);
DebuggableScript[] result = new DebuggableScript[functions.size()];
functions.toArray(result);
return result;
}
private SourceInfo registerSource(String sourceUrl, String source) {
SourceInfo si;
synchronized (sourceNames) {
si = (SourceInfo)sourceNames.get(sourceUrl);
if (si == null) {
si = new SourceInfo(sourceUrl, source);
sourceNames.put(sourceUrl, si);
} else {
si.setSource(source);
}
private static void collectFunctions_r(DebuggableScript function,
ObjArray array)
{
array.add(function);
for (int i = 0; i != function.getFunctionCount(); ++i) {
collectFunctions_r(function.getFunction(i), array);
}
return si;
}
private ScriptItem registerScript(final SourceInfo si,
DebuggableScript fnOrScript)
{
ScriptItem item = new ScriptItem(fnOrScript, si);
si.updateLineInfo(item);
scriptItems.put(fnOrScript, item);
String name = fnOrScript.getFunctionName();
if (name != null && name.length() > 0 && !name.equals("anonymous")) {
functionNames.put(name, item);
}
swingInvokeLater(new Runnable() {
public void run()
{
debugGui.updateFileText(si);
}
});
return item;
public void doBreak() {
breakFlag = true;
}
void handleBreakpointHit(StackFrame frame, Context cx) {
@ -635,15 +749,37 @@ public class Main implements Debugger, ContextListener {
}
}
public DebugFrame getFrame(Context cx, DebuggableScript fnOrScript) {
return new StackFrame(cx, this, fnOrScript);
}
/* end Debugger interface */
void compileScript(String url, String text)
{
Context cx = Context.enter();
try {
cx.compileString(text, url, 1, null);
} finally {
Context.exit();
}
}
Scriptable getScope() {
return (scopeProvider != null) ? scopeProvider.getScope() : null;
void evalScript(String url, String text)
{
Context cx = Context.enter();
try {
Scriptable scope = null;
if (scopeProvider != null) {
scope = scopeProvider.getScope();
}
if (scope == null) {
scope = new ImporterTopLevel(cx);
}
try {
cx.evaluateString(scope, text, url, 1, null);
} catch (JavaScriptException ex) {
throw new RuntimeException(ex.getMessage());
}
} finally {
Context.exit();
}
}
static void swingInvokeLater(Runnable f)
@ -700,21 +836,6 @@ public class Main implements Debugger, ContextListener {
currentContextData = contextData;
}
do {
if (runToCursorFile != null) {
if (url != null && url.equals(runToCursorFile)) {
if (line == runToCursorLine) {
runToCursorFile = null;
} else {
SourceInfo si = frame.sourceInfo();
if (si == null || !si.hasBreakpoint(line))
{
break;
} else {
runToCursorFile = null;
}
}
}
}
int frameCount = contextData.frameCount();
this.frameIndex = frameCount -1;
@ -795,10 +916,6 @@ public class Main implements Debugger, ContextListener {
contextData.stopAtFrameDepth = contextData.frameCount() -1;
}
break;
case RUN_TO_CURSOR:
contextData.breakNextLine = true;
contextData.stopAtFrameDepth = -1;
break;
}
} while (false);
@ -963,8 +1080,9 @@ public class Main implements Debugger, ContextListener {
*
* Remove all breakpoints
*/
public void clearAllBreakpoints() {
Enumeration e = sourceNames.elements();
public void clearAllBreakpoints()
{
Enumeration e = urlToSourceInfo.elements();
while (e.hasMoreElements()) {
SourceInfo si = (SourceInfo)e.nextElement();
si.removeAllBreakpoints();
@ -1036,7 +1154,7 @@ public class Main implements Debugger, ContextListener {
System.setIn(sdb.getIn());
System.setOut(sdb.getOut());
System.setErr(sdb.getErr());
Context.addContextListener(sdb);
sdb.enableForAllNewContexts();
sdb.setScopeProvider(new ScopeProvider() {
public Scriptable getScope() {
return org.mozilla.javascript.tools.shell.Main.getScope();

Просмотреть файл

@ -39,7 +39,7 @@
var x = 10;
var x = 12;
function sleep(millis)
{