* Previous solution didn't work with Rhino running in interpreter mode. Provide a

hook in RhinoException to make JS stack traces work with any optimization mode.
  See https://bugzilla.mozilla.org/show_bug.cgi?id=363058
This commit is contained in:
hns 2006-12-07 12:12:14 +00:00
parent f3ce79f6c4
commit b210d5cd11

View file

@ -16,16 +16,22 @@
package helma.scripting; package helma.scripting;
import java.util.List; import org.mozilla.javascript.RhinoException;
import java.util.ArrayList;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.FilenameFilter;
import java.io.File;
/** /**
* The base class for exceptions thrown by Helma scripting package * The base class for wrapped exceptions thrown by invocation of the scripting engine.
* If the wrapped exception is a RhinoException, the script stack trace will be
* prepended to the actual java stack trace in stack dumps.
*/ */
public class ScriptingException extends Exception { public class ScriptingException extends Exception {
String scriptStack = null;
/** /**
* Construct a ScriptingException given an error message and wrapped exception. * Construct a ScriptingException given an error message and wrapped exception.
* @param message the message * @param message the message
@ -42,17 +48,16 @@ public class ScriptingException extends Exception {
* @param cause the original exception * @param cause the original exception
*/ */
private void setScriptStack(Throwable cause) { private void setScriptStack(Throwable cause) {
List list = new ArrayList(); if (cause instanceof RhinoException) {
StackTraceElement[] stack = cause.getStackTrace(); FilenameFilter filter = new FilenameFilter() {
for (int i = 0; i < stack.length; i++) { public boolean accept(File dir, String name) {
StackTraceElement e = stack[i]; return name.endsWith(".js") ||
String name = e.getFileName(); name.endsWith(".hac") ||
if (e.getLineNumber() > -1 && name.endsWith(".hsp");
(name.endsWith(".js") || name.endsWith(".hac"))) { }
list.add(e); };
} scriptStack = ((RhinoException) cause).getScriptStackTrace(filter);
} }
setStackTrace((StackTraceElement[]) list.toArray(new StackTraceElement[list.size()]));
} }
@ -61,87 +66,28 @@ public class ScriptingException extends Exception {
*/ */
public void printStackTrace(PrintStream s) { public void printStackTrace(PrintStream s) {
synchronized (s) { synchronized (s) {
s.println(this); if (scriptStack != null) {
StackTraceElement[] trace = getStackTrace(); s.println(this);
for (int i=0; i < trace.length; i++) s.print(scriptStack);
s.println("\tat " + trace[i].getFileName() + ":" + s.print("Full trace: ");
trace[i].getLineNumber()); }
Throwable ourCause = getCause(); getCause().printStackTrace(s);
if (ourCause != null)
printStackTraceAsCause(ourCause, s, trace);
} }
} }
/*
* Adaption from Throwable.printTraceAsCause() to be callable from this class.
*/
private static void printStackTraceAsCause(Throwable t, PrintStream s,
StackTraceElement[] causedTrace)
{
// assert Thread.holdsLock(s);
// Compute number of frames in common between this and caused
StackTraceElement[] trace = t.getStackTrace();
int m = trace.length-1, n = causedTrace.length-1;
while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {
m--; n--;
}
int framesInCommon = trace.length - 1 - m;
s.println("Caused by: " + t);
for (int i=0; i <= m; i++)
s.println("\tat " + trace[i]);
if (framesInCommon != 0)
s.println("\t... " + framesInCommon + " more");
// Recurse if t has a cause
Throwable theCause = t.getCause();
if (theCause != null)
printStackTraceAsCause(theCause, s, trace);
}
/* /*
* Adaption from Throwable.printStackTrace() to only print Script file stack elements. * Adaption from Throwable.printStackTrace() to only print Script file stack elements.
*/ */
public void printStackTrace(PrintWriter s) { public void printStackTrace(PrintWriter s) {
synchronized (s) { synchronized (s) {
s.println(this); if (scriptStack != null) {
StackTraceElement[] trace = getStackTrace(); s.println(this);
for (int i=0; i < trace.length; i++) s.print(scriptStack);
s.println("\tat " + trace[i].getFileName() + ":" + s.print("Full trace: ");
trace[i].getLineNumber()); }
Throwable ourCause = getCause(); getCause().printStackTrace(s);
if (ourCause != null)
printStackTraceAsCause(ourCause, s, trace);
} }
} }
/* }
* Adaption from Throwable.printTraceAsCause() to be callable from this class.
*/
private static void printStackTraceAsCause(Throwable t, PrintWriter s,
StackTraceElement[] causedTrace)
{
// assert Thread.holdsLock(s);
// Compute number of frames in common between this and caused
StackTraceElement[] trace = t.getStackTrace();
int m = trace.length-1, n = causedTrace.length-1;
while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {
m--; n--;
}
int framesInCommon = trace.length - 1 - m;
s.println("Caused by: " + t);
for (int i=0; i <= m; i++)
s.println("\tat " + trace[i]);
if (framesInCommon != 0)
s.println("\t... " + framesInCommon + " more");
// Recurse if t has a cause
Throwable theCause = t.getCause();
if (theCause != null)
printStackTraceAsCause(theCause, s, trace);
}
}