diff --git a/src/org/mozilla/javascript/RhinoException.java b/src/org/mozilla/javascript/RhinoException.java
index dfd2820c29..6fb2109cd9 100644
--- a/src/org/mozilla/javascript/RhinoException.java
+++ b/src/org/mozilla/javascript/RhinoException.java
@@ -4,7 +4,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
package org.mozilla.javascript;
import java.io.CharArrayWriter;
@@ -16,31 +15,23 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-/**
- * The class of exceptions thrown by the JavaScript engine.
- */
-public abstract class RhinoException extends RuntimeException
-{
+/** The class of exceptions thrown by the JavaScript engine. */
+public abstract class RhinoException extends RuntimeException {
private static final Pattern JAVA_STACK_PATTERN = Pattern.compile("_c_(.*)_\\d+");
- RhinoException()
- {
+ RhinoException() {
Evaluator e = Context.createInterpreter();
- if (e != null)
- e.captureStackInfo(this);
+ if (e != null) e.captureStackInfo(this);
}
- RhinoException(String details)
- {
+ RhinoException(String details) {
super(details);
Evaluator e = Context.createInterpreter();
- if (e != null)
- e.captureStackInfo(this);
+ if (e != null) e.captureStackInfo(this);
}
@Override
- public final String getMessage()
- {
+ public final String getMessage() {
String details = details();
if (sourceName == null || lineNumber <= 0) {
return details;
@@ -56,108 +47,85 @@ public final String getMessage()
return buf.toString();
}
- public String details()
- {
+ public String details() {
return super.getMessage();
}
/**
- * Get the uri of the script source containing the error, or null
- * if that information is not available.
+ * Get the uri of the script source containing the error, or null if that information is not
+ * available.
*/
- public final String sourceName()
- {
+ public final String sourceName() {
return sourceName;
}
/**
* Initialize the uri of the script source containing the error.
*
- * @param sourceName the uri of the script source responsible for the error.
- * It should not be null
.
- *
+ * @param sourceName the uri of the script source responsible for the error. It should not be
+ * null
.
* @throws IllegalStateException if the method is called more then once.
*/
- public final void initSourceName(String sourceName)
- {
+ public final void initSourceName(String sourceName) {
if (sourceName == null) throw new IllegalArgumentException();
if (this.sourceName != null) throw new IllegalStateException();
this.sourceName = sourceName;
}
- /**
- * Returns the line number of the statement causing the error,
- * or zero if not available.
- */
- public final int lineNumber()
- {
+ /** Returns the line number of the statement causing the error, or zero if not available. */
+ public final int lineNumber() {
return lineNumber;
}
/**
* Initialize the line number of the script statement causing the error.
*
- * @param lineNumber the line number in the script source.
- * It should be positive number.
- *
+ * @param lineNumber the line number in the script source. It should be positive number.
* @throws IllegalStateException if the method is called more then once.
*/
- public final void initLineNumber(int lineNumber)
- {
+ public final void initLineNumber(int lineNumber) {
if (lineNumber <= 0) throw new IllegalArgumentException(String.valueOf(lineNumber));
if (this.lineNumber > 0) throw new IllegalStateException();
this.lineNumber = lineNumber;
}
- /**
- * The column number of the location of the error, or zero if unknown.
- */
- public final int columnNumber()
- {
+ /** The column number of the location of the error, or zero if unknown. */
+ public final int columnNumber() {
return columnNumber;
}
/**
* Initialize the column number of the script statement causing the error.
*
- * @param columnNumber the column number in the script source.
- * It should be positive number.
- *
+ * @param columnNumber the column number in the script source. It should be positive number.
* @throws IllegalStateException if the method is called more then once.
*/
- public final void initColumnNumber(int columnNumber)
- {
+ public final void initColumnNumber(int columnNumber) {
if (columnNumber <= 0) throw new IllegalArgumentException(String.valueOf(columnNumber));
if (this.columnNumber > 0) throw new IllegalStateException();
this.columnNumber = columnNumber;
}
- /**
- * The source text of the line causing the error, or null if unknown.
- */
- public final String lineSource()
- {
+ /** The source text of the line causing the error, or null if unknown. */
+ public final String lineSource() {
return lineSource;
}
/**
* Initialize the text of the source line containing the error.
*
- * @param lineSource the text of the source line responsible for the error.
- * It should not be null
.
- *
+ * @param lineSource the text of the source line responsible for the error. It should not be
+ * null
.
* @throws IllegalStateException if the method is called more then once.
*/
- public final void initLineSource(String lineSource)
- {
+ public final void initLineSource(String lineSource) {
if (lineSource == null) throw new IllegalArgumentException();
if (this.lineSource != null) throw new IllegalStateException();
this.lineSource = lineSource;
}
- final void recordErrorOrigin(String sourceName, int lineNumber,
- String lineSource, int columnNumber)
- {
+ final void recordErrorOrigin(
+ String sourceName, int lineNumber, String lineSource, int columnNumber) {
// XXX: for compatibility allow for now -1 to mean 0
if (lineNumber == -1) {
lineNumber = 0;
@@ -177,38 +145,33 @@ final void recordErrorOrigin(String sourceName, int lineNumber,
}
}
- private String generateStackTrace()
- {
+ private String generateStackTrace() {
// Get stable reference to work properly with concurrent access
CharArrayWriter writer = new CharArrayWriter();
super.printStackTrace(new PrintWriter(writer));
String origStackTrace = writer.toString();
Evaluator e = Context.createInterpreter();
- if (e != null)
- return e.getPatchedStack(this, origStackTrace);
+ if (e != null) return e.getPatchedStack(this, origStackTrace);
return null;
}
/**
- * Get a string representing the script stack of this exception.
- * If optimization is enabled, this includes java stack elements
- * whose source and method names suggest they have been generated
- * by the Rhino script compiler.
+ * Get a string representing the script stack of this exception. If optimization is enabled,
+ * this includes java stack elements whose source and method names suggest they have been
+ * generated by the Rhino script compiler.
+ *
* @return a script stack dump
* @since 1.6R6
*/
- public String getScriptStackTrace()
- {
+ public String getScriptStackTrace() {
return getScriptStackTrace(NativeError.DEFAULT_STACK_LIMIT, null);
}
/**
- * Get a string representing the script stack of this exception.
- * If optimization is enabled, this includes java stack elements
- * whose source and method names suggest they have been generated
- * by the Rhino script compiler.
- * The optional "limit" parameter limits the number of stack frames returned.
- * The "functionName" parameter will exclude any stack frames "below" the
+ * Get a string representing the script stack of this exception. If optimization is enabled,
+ * this includes java stack elements whose source and method names suggest they have been
+ * generated by the Rhino script compiler. The optional "limit" parameter limits the number of
+ * stack frames returned. The "functionName" parameter will exclude any stack frames "below" the
* specified function on the stack.
*
* @param limit the number of stack frames returned
@@ -216,14 +179,12 @@ public String getScriptStackTrace()
* @return a script stack dump
* @since 1.8.0
*/
- public String getScriptStackTrace(int limit, String functionName)
- {
+ public String getScriptStackTrace(int limit, String functionName) {
ScriptStackElement[] stack = getScriptStack(limit, functionName);
return formatStackTrace(stack, details());
}
- static String formatStackTrace(ScriptStackElement[] stack, String message)
- {
+ static String formatStackTrace(ScriptStackElement[] stack, String message) {
StringBuilder buffer = new StringBuilder();
String lineSeparator = SecurityUtilities.getSystemProperty("line.separator");
@@ -235,42 +196,46 @@ static String formatStackTrace(ScriptStackElement[] stack, String message)
for (ScriptStackElement elem : stack) {
switch (stackStyle) {
- case MOZILLA:
- elem.renderMozillaStyle(buffer);
- break;
- case V8:
- elem.renderV8Style(buffer);
- break;
- case RHINO:
- elem.renderJavaStyle(buffer);
- break;
+ case MOZILLA:
+ elem.renderMozillaStyle(buffer);
+ buffer.append(lineSeparator);
+ break;
+ case MOZILLA_LF:
+ elem.renderMozillaStyle(buffer);
+ buffer.append('\n');
+ break;
+ case V8:
+ elem.renderV8Style(buffer);
+ buffer.append(lineSeparator);
+ break;
+ case RHINO:
+ elem.renderJavaStyle(buffer);
+ buffer.append(lineSeparator);
+ break;
}
- buffer.append(lineSeparator);
}
return buffer.toString();
}
/**
* Get a string representing the script stack of this exception.
- * @deprecated the filter argument is ignored as we are able to
- * recognize script stack elements by our own. Use
- * #getScriptStackTrace() instead.
+ *
+ * @deprecated the filter argument is ignored as we are able to recognize script stack elements
+ * by our own. Use #getScriptStackTrace() instead.
* @param filter ignored
* @return a script stack dump
* @since 1.6R6
*/
@Deprecated
- public String getScriptStackTrace(FilenameFilter filter)
- {
+ public String getScriptStackTrace(FilenameFilter filter) {
return getScriptStackTrace();
}
/**
- * Get the script stack of this exception as an array of
- * {@link ScriptStackElement}s.
- * If optimization is enabled, this includes java stack elements
- * whose source and method names suggest they have been generated
- * by the Rhino script compiler.
+ * Get the script stack of this exception as an array of {@link ScriptStackElement}s. If
+ * optimization is enabled, this includes java stack elements whose source and method names
+ * suggest they have been generated by the Rhino script compiler.
+ *
* @return the script stack for this exception
* @since 1.7R3
*/
@@ -279,14 +244,13 @@ public ScriptStackElement[] getScriptStack() {
}
/**
- * Get the script stack of this exception as an array of
- * {@link ScriptStackElement}s.
- * If optimization is enabled, this includes java stack elements
- * whose source and method names suggest they have been generated
- * by the Rhino script compiler.
+ * Get the script stack of this exception as an array of {@link ScriptStackElement}s. If
+ * optimization is enabled, this includes java stack elements whose source and method names
+ * suggest they have been generated by the Rhino script compiler.
*
* @param limit the number of stack frames returned, or -1 for unlimited
- * @param hideFunction the name of a function on the stack -- frames below it will be ignored, or null
+ * @param hideFunction the name of a function on the stack -- frames below it will be ignored,
+ * or null
* @return the script stack for this exception
* @since 1.8.0
*/
@@ -317,8 +281,8 @@ public ScriptStackElement[] getScriptStack(int limit, String hideFunction) {
Matcher match = JAVA_STACK_PATTERN.matcher(methodName);
// the method representing the main script is always "_c_script_0" -
// at least we hope so
- methodName = !"_c_script_0".equals(methodName) && match.find() ?
- match.group(1) : null;
+ methodName =
+ !"_c_script_0".equals(methodName) && match.find() ? match.group(1) : null;
if (!printStarted && hideFunction.equals(methodName)) {
printStarted = true;
@@ -345,10 +309,8 @@ public ScriptStackElement[] getScriptStack(int limit, String hideFunction) {
return list.toArray(new ScriptStackElement[list.size()]);
}
-
@Override
- public void printStackTrace(PrintWriter s)
- {
+ public void printStackTrace(PrintWriter s) {
if (interpreterStackInfo == null) {
super.printStackTrace(s);
} else {
@@ -357,8 +319,7 @@ public void printStackTrace(PrintWriter s)
}
@Override
- public void printStackTrace(PrintStream s)
- {
+ public void printStackTrace(PrintStream s) {
if (interpreterStackInfo == null) {
super.printStackTrace(s);
} else {
@@ -367,11 +328,10 @@ public void printStackTrace(PrintStream s)
}
/**
- * Returns true if subclasses of RhinoException
- * use the Mozilla/Firefox style of rendering script stacks
- * (functionName()@fileName:lineNumber
)
- * instead of Rhino's own Java-inspired format
- * ( at fileName:lineNumber (functionName)
).
+ * Returns true if subclasses of RhinoException
use the Mozilla/Firefox style of
+ * rendering script stacks (functionName()@fileName:lineNumber
) instead of Rhino's
+ * own Java-inspired format ( at fileName:lineNumber (functionName)
).
+ *
* @return true if stack is rendered in Mozilla/Firefox style
* @see ScriptStackElement
* @since 1.7R3
@@ -381,12 +341,11 @@ public static boolean usesMozillaStackStyle() {
}
/**
- * Tell subclasses of RhinoException
whether to
- * use the Mozilla/Firefox style of rendering script stacks
- * (functionName()@fileName:lineNumber
)
- * instead of Rhino's own Java-inspired format
- * ( at fileName:lineNumber (functionName)
).
- * Use "setStackStyle" to select between more than just the "Mozilla" and "Rhino" formats.
+ * Tell subclasses of RhinoException
whether to use the Mozilla/Firefox style of
+ * rendering script stacks (functionName()@fileName:lineNumber
) instead of Rhino's
+ * own Java-inspired format ( at fileName:lineNumber (functionName)
). Use
+ * "setStackStyle" to select between more than just the "Mozilla" and "Rhino" formats.
+ *
* @param flag whether to render stacks in Mozilla/Firefox style
* @see ScriptStackElement
* @since 1.7R3
@@ -398,6 +357,7 @@ public static void useMozillaStackStyle(boolean flag) {
/**
* Specify the stack style to use from between three different formats: "Rhino" (the default),
* "Mozilla", and "V8." See StackStyle for information about each.
+ *
* @param style the style to select -- an instance of the StackStyle class
* @see StackStyle
* @since 1.8.0
@@ -406,10 +366,7 @@ public static void setStackStyle(StackStyle style) {
stackStyle = style;
}
- /**
- * Return the current stack style in use.
- * Return the current stack style in use.
- */
+ /** Return the current stack style in use. Return the current stack style in use. */
public static StackStyle getStackStyle() {
return stackStyle;
}
diff --git a/src/org/mozilla/javascript/StackStyle.java b/src/org/mozilla/javascript/StackStyle.java
index 911f4a83e1..1805e9a563 100644
--- a/src/org/mozilla/javascript/StackStyle.java
+++ b/src/org/mozilla/javascript/StackStyle.java
@@ -4,27 +4,29 @@
package org.mozilla.javascript;
-/**
- * This class distinguishes between the three different supported stack trace formats.
- */
-
+/** This class distinguishes between the three different supported stack trace formats. */
public enum StackStyle {
/**
- * This is the default stack trace style in Rhino, which is like Java:
- * at fileName:lineNumber (functionName)
+ * This is the default stack trace style in Rhino, which is like Java:
+ * at fileName:lineNumber (functionName)
*/
RHINO,
/**
- * This stack trace style comes from the old Mozilla code:
- * functionName()@fileName:lineNumber
+ * This stack trace style comes from the old Mozilla code:
+ * functionName()@fileName:lineNumber
*/
MOZILLA,
/**
- * This stack trace style matches that output from V8, either:
- * at functionName (fileName:lineNumber:columnNumber)
- * or, for anonymous functions:
+ * This is the same as MOZILLA but uses LF as speparator instead of the system dependent line
+ * separator.
+ */
+ MOZILLA_LF,
+
+ /**
+ * This stack trace style matches that output from V8, either:
+ * at functionName (fileName:lineNumber:columnNumber)
or, for anonymous functions:
* at fileName:lineNumber:columnNumber
*/
V8
diff --git a/testsrc/jstests/extensions/stack-traces-mozilla-lf.js b/testsrc/jstests/extensions/stack-traces-mozilla-lf.js
new file mode 100644
index 0000000000..443f22ddb4
--- /dev/null
+++ b/testsrc/jstests/extensions/stack-traces-mozilla-lf.js
@@ -0,0 +1,230 @@
+load("testsrc/assert.js");
+
+function nestedThrower(msg) {
+ throw new Error(msg);
+}
+function parentThrower(msg) {
+ nestedThrower(msg);
+}
+function grandparentThrower(msg) {
+ parentThrower(msg);
+}
+function ObjectThrower(msg) {
+ nestedThrower(msg);
+}
+function nestedCapture(o, f) {
+ Error.captureStackTrace(o, f);
+}
+function parentCapture(o, f) {
+ nestedCapture(o, f);
+}
+function grandParentCapture(o, f) {
+ parentCapture(o, f);
+}
+function countLines(msg) {
+ if (!msg) {
+ return 0;
+ }
+ // Subtract one for the newline at the end
+ return msg.split('\n').length - 1;
+}
+
+// Test that toString contains the error but not the stack
+// and test that the stack contains the file name
+try {
+ throw new Error('Test 1');
+} catch (e) {
+ assertFalse(e.stack == undefined);
+ assertTrue(/Test 1/.test(e.toString()));
+ assertFalse(/stack-traces-mozilla-lf.js/.test(e.toString()));
+ assertFalse(/Test 1/.test(e.stack));
+ assertTrue(/stack-traces-mozilla-lf.js/.test(e.stack));
+}
+
+// Assert that the function name is nested inside a nested stack trace
+try {
+ nestedThrower('Nested 1');
+} catch (e) {
+ assertFalse(/Nested 1/.test(e.stack));
+ assertTrue(/nestedThrower/.test(e.stack));
+}
+
+// Do the same for a second level of nesting
+try {
+ parentThrower('Nested 2');
+} catch (e) {
+ assertFalse(/Nested 2/.test(e.stack));
+ assertTrue(/nestedThrower/.test(e.stack));
+ assertTrue(/parentThrower/.test(e.stack));
+}
+
+// Do the same for a constructor
+try {
+ new ObjectThrower('Nested 3');
+} catch (e) {
+ assertFalse(/Nested 3/.test(e.stack));
+ assertTrue(/nestedThrower/.test(e.stack));
+ assertTrue(/ObjectThrower/.test(e.stack));
+}
+
+// Count stack lines before and after changing limit
+try {
+ grandparentThrower('Count 1');
+} catch (e) {
+ assertTrue(countLines(e.stack) >= 3);
+}
+
+assertTrue(Error.stackTraceLimit != undefined);
+Error.stackTraceLimit = 2;
+assertEquals(2, Error.stackTraceLimit);
+
+try {
+ grandparentThrower('Count 2');
+} catch (e) {
+ assertEquals(2, countLines(e.stack));
+}
+
+Error.stackTraceLimit = 0;
+assertEquals(0, Error.stackTraceLimit);
+
+try {
+ grandparentThrower('Count 3');
+} catch (e) {
+ assertEquals(0, countLines(e.stack));
+}
+
+Error.stackTraceLimit = Infinity;
+assertEquals(Infinity, Error.stackTraceLimit);
+
+try {
+ grandparentThrower('Count 1');
+} catch (e) {
+ assertTrue(countLines(e.stack) >= 3);
+}
+
+// Test captureStackTrace
+
+var o = {};
+grandParentCapture(o);
+assertTrue(/nestedCapture/.test(o.stack));
+assertTrue(/parentCapture/.test(o.stack));
+assertTrue(/grandParentCapture/.test(o.stack));
+
+// Put in a function to be hidden from the stack
+
+var m = {};
+grandParentCapture(m, parentCapture);
+assertTrue(/grandParentCapture/.test(m.stack));
+assertFalse(/parentCapture/.test(m.stack));
+assertFalse(/nestedCapture/.test(m.stack));
+
+// Put in a function not in the stack
+
+var n = {};
+grandParentCapture(n, print);
+assertFalse(/nestedCapture/.test(n.stack));
+assertFalse(/parentCapture/.test(n.stack));
+assertFalse(/grandParentCapture/.test(n.stack));
+
+// Test prepareStackTrace
+
+assertEquals(undefined, Error.prepareStackTrace);
+
+var prepareCalled = false;
+
+function diagnoseStack(err, stack) {
+ var s = '';
+ prepareCalled = true;
+ stack.forEach(function (e) {
+ assertEquals('object', typeof e);
+ s += e.getFunctionName() + ' ';
+ s += e.getMethodName() + ' ';
+ s += e.getFileName() + ' ';
+ s += e.getLineNumber() + ' ';
+ s += '\n';
+ });
+ return s;
+}
+Error.prepareStackTrace = diagnoseStack;
+
+var s1 = {};
+grandParentCapture(s1);
+assertTrue(/nestedCapture/.test(s1.stack));
+assertTrue(/parentCapture/.test(s1.stack));
+assertTrue(/grandParentCapture/.test(s1.stack));
+assertTrue(prepareCalled);
+
+// Test that it is limited by the function flag as above
+
+var s2 = {};
+grandParentCapture(s2, parentCapture);
+assertFalse(/nestedCapture/.test(s2.stack));
+assertFalse(/parentCapture/.test(s2.stack));
+assertTrue(/grandParentCapture/.test(s2.stack));
+
+// Test that it all works on a throw. Note that the error text isn't included.
+
+try {
+ grandparentThrower('Custom 1');
+} catch (e) {
+ assertFalse(/Custom 1/.test(e.stack));
+ assertTrue(/nestedThrower/.test(e.stack));
+ assertTrue(/parentThrower/.test(e.stack));
+ assertTrue(/grandparentThrower/.test(e.stack));
+}
+
+// And test that it works the old way when we format it back
+Error.prepareStackTrace = undefined;
+
+try {
+ grandparentThrower('Custom 2');
+} catch (e) {
+ assertFalse(/Custom 2/.test(e.stack));
+ assertTrue(/nestedThrower/.test(e.stack));
+ assertTrue(/parentThrower/.test(e.stack));
+ assertTrue(/grandparentThrower/.test(e.stack));
+}
+
+// test that all the functions on a stack frame work
+
+function printFrame(l, f) {
+ var o =
+ {typeofThis: typeof f.getThis(),
+ typeName: f.getTypeName(),
+ function: f.getFunction(),
+ functionName: f.getFunctionName(),
+ methodName: f.getMethodName(),
+ fileName: f.getFileName(),
+ lineNumber: f.getLineNumber(),
+ columnNumber: f.getColumnNumber(),
+ evalOrigin: f.getEvalOrigin(),
+ topLevel: f.isToplevel(),
+ eval: f.isEval(),
+ native: f.isNative(),
+ constructor: f.isConstructor()
+ };
+
+ l.push(o);
+ return l;
+}
+
+Error.prepareStackTrace = function (e, frames) {
+ return frames.reduce(printFrame, []);
+};
+
+try {
+ grandparentThrower('testing stack');
+} catch (e) {
+ e.stack.forEach(function (f) {
+ verifyFrame(f);
+ });
+}
+
+function verifyFrame(f) {
+ assertEquals(typeof f.fileName, 'string');
+ assertEquals(typeof f.lineNumber, 'number');
+ assertEquals(typeof f.topLevel, 'boolean');
+ assertEquals(typeof f.eval, 'boolean');
+ assertEquals(typeof f.native, 'boolean');
+ assertEquals(typeof f.constructor, 'boolean');
+}
diff --git a/testsrc/jstests/extensions/stack-traces-mozilla.js b/testsrc/jstests/extensions/stack-traces-mozilla.js
new file mode 100644
index 0000000000..fa27d2bfac
--- /dev/null
+++ b/testsrc/jstests/extensions/stack-traces-mozilla.js
@@ -0,0 +1,230 @@
+load("testsrc/assert.js");
+
+function nestedThrower(msg) {
+ throw new Error(msg);
+}
+function parentThrower(msg) {
+ nestedThrower(msg);
+}
+function grandparentThrower(msg) {
+ parentThrower(msg);
+}
+function ObjectThrower(msg) {
+ nestedThrower(msg);
+}
+function nestedCapture(o, f) {
+ Error.captureStackTrace(o, f);
+}
+function parentCapture(o, f) {
+ nestedCapture(o, f);
+}
+function grandParentCapture(o, f) {
+ parentCapture(o, f);
+}
+function countLines(msg) {
+ if (!msg) {
+ return 0;
+ }
+ // Subtract one for the newline at the end
+ return msg.split('\n').length - 1;
+}
+
+// Test that toString contains the error but not the stack
+// and test that the stack contains the file name
+try {
+ throw new Error('Test 1');
+} catch (e) {
+ assertFalse(e.stack == undefined);
+ assertTrue(/Test 1/.test(e.toString()));
+ assertFalse(/stack-traces-mozilla.js/.test(e.toString()));
+ assertFalse(/Test 1/.test(e.stack));
+ assertTrue(/stack-traces-mozilla.js/.test(e.stack));
+}
+
+// Assert that the function name is nested inside a nested stack trace
+try {
+ nestedThrower('Nested 1');
+} catch (e) {
+ assertFalse(/Nested 1/.test(e.stack));
+ assertTrue(/nestedThrower/.test(e.stack));
+}
+
+// Do the same for a second level of nesting
+try {
+ parentThrower('Nested 2');
+} catch (e) {
+ assertFalse(/Nested 2/.test(e.stack));
+ assertTrue(/nestedThrower/.test(e.stack));
+ assertTrue(/parentThrower/.test(e.stack));
+}
+
+// Do the same for a constructor
+try {
+ new ObjectThrower('Nested 3');
+} catch (e) {
+ assertFalse(/Nested 3/.test(e.stack));
+ assertTrue(/nestedThrower/.test(e.stack));
+ assertTrue(/ObjectThrower/.test(e.stack));
+}
+
+// Count stack lines before and after changing limit
+try {
+ grandparentThrower('Count 1');
+} catch (e) {
+ assertTrue(countLines(e.stack) >= 3);
+}
+
+assertTrue(Error.stackTraceLimit != undefined);
+Error.stackTraceLimit = 2;
+assertEquals(2, Error.stackTraceLimit);
+
+try {
+ grandparentThrower('Count 2');
+} catch (e) {
+ assertEquals(2, countLines(e.stack));
+}
+
+Error.stackTraceLimit = 0;
+assertEquals(0, Error.stackTraceLimit);
+
+try {
+ grandparentThrower('Count 3');
+} catch (e) {
+ assertEquals(0, countLines(e.stack));
+}
+
+Error.stackTraceLimit = Infinity;
+assertEquals(Infinity, Error.stackTraceLimit);
+
+try {
+ grandparentThrower('Count 1');
+} catch (e) {
+ assertTrue(countLines(e.stack) >= 3);
+}
+
+// Test captureStackTrace
+
+var o = {};
+grandParentCapture(o);
+assertTrue(/nestedCapture/.test(o.stack));
+assertTrue(/parentCapture/.test(o.stack));
+assertTrue(/grandParentCapture/.test(o.stack));
+
+// Put in a function to be hidden from the stack
+
+var m = {};
+grandParentCapture(m, parentCapture);
+assertTrue(/grandParentCapture/.test(m.stack));
+assertFalse(/parentCapture/.test(m.stack));
+assertFalse(/nestedCapture/.test(m.stack));
+
+// Put in a function not in the stack
+
+var n = {};
+grandParentCapture(n, print);
+assertFalse(/nestedCapture/.test(n.stack));
+assertFalse(/parentCapture/.test(n.stack));
+assertFalse(/grandParentCapture/.test(n.stack));
+
+// Test prepareStackTrace
+
+assertEquals(undefined, Error.prepareStackTrace);
+
+var prepareCalled = false;
+
+function diagnoseStack(err, stack) {
+ var s = '';
+ prepareCalled = true;
+ stack.forEach(function (e) {
+ assertEquals('object', typeof e);
+ s += e.getFunctionName() + ' ';
+ s += e.getMethodName() + ' ';
+ s += e.getFileName() + ' ';
+ s += e.getLineNumber() + ' ';
+ s += '\n';
+ });
+ return s;
+}
+Error.prepareStackTrace = diagnoseStack;
+
+var s1 = {};
+grandParentCapture(s1);
+assertTrue(/nestedCapture/.test(s1.stack));
+assertTrue(/parentCapture/.test(s1.stack));
+assertTrue(/grandParentCapture/.test(s1.stack));
+assertTrue(prepareCalled);
+
+// Test that it is limited by the function flag as above
+
+var s2 = {};
+grandParentCapture(s2, parentCapture);
+assertFalse(/nestedCapture/.test(s2.stack));
+assertFalse(/parentCapture/.test(s2.stack));
+assertTrue(/grandParentCapture/.test(s2.stack));
+
+// Test that it all works on a throw. Note that the error text isn't included.
+
+try {
+ grandparentThrower('Custom 1');
+} catch (e) {
+ assertFalse(/Custom 1/.test(e.stack));
+ assertTrue(/nestedThrower/.test(e.stack));
+ assertTrue(/parentThrower/.test(e.stack));
+ assertTrue(/grandparentThrower/.test(e.stack));
+}
+
+// And test that it works the old way when we format it back
+Error.prepareStackTrace = undefined;
+
+try {
+ grandparentThrower('Custom 2');
+} catch (e) {
+ assertFalse(/Custom 2/.test(e.stack));
+ assertTrue(/nestedThrower/.test(e.stack));
+ assertTrue(/parentThrower/.test(e.stack));
+ assertTrue(/grandparentThrower/.test(e.stack));
+}
+
+// test that all the functions on a stack frame work
+
+function printFrame(l, f) {
+ var o =
+ {typeofThis: typeof f.getThis(),
+ typeName: f.getTypeName(),
+ function: f.getFunction(),
+ functionName: f.getFunctionName(),
+ methodName: f.getMethodName(),
+ fileName: f.getFileName(),
+ lineNumber: f.getLineNumber(),
+ columnNumber: f.getColumnNumber(),
+ evalOrigin: f.getEvalOrigin(),
+ topLevel: f.isToplevel(),
+ eval: f.isEval(),
+ native: f.isNative(),
+ constructor: f.isConstructor()
+ };
+
+ l.push(o);
+ return l;
+}
+
+Error.prepareStackTrace = function (e, frames) {
+ return frames.reduce(printFrame, []);
+};
+
+try {
+ grandparentThrower('testing stack');
+} catch (e) {
+ e.stack.forEach(function (f) {
+ verifyFrame(f);
+ });
+}
+
+function verifyFrame(f) {
+ assertEquals(typeof f.fileName, 'string');
+ assertEquals(typeof f.lineNumber, 'number');
+ assertEquals(typeof f.topLevel, 'boolean');
+ assertEquals(typeof f.eval, 'boolean');
+ assertEquals(typeof f.native, 'boolean');
+ assertEquals(typeof f.constructor, 'boolean');
+}
diff --git a/testsrc/jstests/extensions/stack-traces-rhino.js b/testsrc/jstests/extensions/stack-traces-rhino.js
new file mode 100644
index 0000000000..a1b218b822
--- /dev/null
+++ b/testsrc/jstests/extensions/stack-traces-rhino.js
@@ -0,0 +1,230 @@
+load("testsrc/assert.js");
+
+function nestedThrower(msg) {
+ throw new Error(msg);
+}
+function parentThrower(msg) {
+ nestedThrower(msg);
+}
+function grandparentThrower(msg) {
+ parentThrower(msg);
+}
+function ObjectThrower(msg) {
+ nestedThrower(msg);
+}
+function nestedCapture(o, f) {
+ Error.captureStackTrace(o, f);
+}
+function parentCapture(o, f) {
+ nestedCapture(o, f);
+}
+function grandParentCapture(o, f) {
+ parentCapture(o, f);
+}
+function countLines(msg) {
+ if (!msg) {
+ return 0;
+ }
+ // Subtract one for the newline at the end
+ return msg.split('\n').length - 1;
+}
+
+// Test that toString contains the error but not the stack
+// and test that the stack contains the file name
+try {
+ throw new Error('Test 1');
+} catch (e) {
+ assertFalse(e.stack == undefined);
+ assertTrue(/Test 1/.test(e.toString()));
+ assertFalse(/stack-traces-rhino.js/.test(e.toString()));
+ assertFalse(/Test 1/.test(e.stack));
+ assertTrue(/stack-traces-rhino.js/.test(e.stack));
+}
+
+// Assert that the function name is nested inside a nested stack trace
+try {
+ nestedThrower('Nested 1');
+} catch (e) {
+ assertFalse(/Nested 1/.test(e.stack));
+ assertTrue(/nestedThrower/.test(e.stack));
+}
+
+// Do the same for a second level of nesting
+try {
+ parentThrower('Nested 2');
+} catch (e) {
+ assertFalse(/Nested 2/.test(e.stack));
+ assertTrue(/nestedThrower/.test(e.stack));
+ assertTrue(/parentThrower/.test(e.stack));
+}
+
+// Do the same for a constructor
+try {
+ new ObjectThrower('Nested 3');
+} catch (e) {
+ assertFalse(/Nested 3/.test(e.stack));
+ assertTrue(/nestedThrower/.test(e.stack));
+ assertTrue(/ObjectThrower/.test(e.stack));
+}
+
+// Count stack lines before and after changing limit
+try {
+ grandparentThrower('Count 1');
+} catch (e) {
+ assertTrue(countLines(e.stack) >= 3);
+}
+
+assertTrue(Error.stackTraceLimit != undefined);
+Error.stackTraceLimit = 2;
+assertEquals(2, Error.stackTraceLimit);
+
+try {
+ grandparentThrower('Count 2');
+} catch (e) {
+ assertEquals(2, countLines(e.stack));
+}
+
+Error.stackTraceLimit = 0;
+assertEquals(0, Error.stackTraceLimit);
+
+try {
+ grandparentThrower('Count 3');
+} catch (e) {
+ assertEquals(0, countLines(e.stack));
+}
+
+Error.stackTraceLimit = Infinity;
+assertEquals(Infinity, Error.stackTraceLimit);
+
+try {
+ grandparentThrower('Count 1');
+} catch (e) {
+ assertTrue(countLines(e.stack) >= 3);
+}
+
+// Test captureStackTrace
+
+var o = {};
+grandParentCapture(o);
+assertTrue(/nestedCapture/.test(o.stack));
+assertTrue(/parentCapture/.test(o.stack));
+assertTrue(/grandParentCapture/.test(o.stack));
+
+// Put in a function to be hidden from the stack
+
+var m = {};
+grandParentCapture(m, parentCapture);
+assertTrue(/grandParentCapture/.test(m.stack));
+assertFalse(/parentCapture/.test(m.stack));
+assertFalse(/nestedCapture/.test(m.stack));
+
+// Put in a function not in the stack
+
+var n = {};
+grandParentCapture(n, print);
+assertFalse(/nestedCapture/.test(n.stack));
+assertFalse(/parentCapture/.test(n.stack));
+assertFalse(/grandParentCapture/.test(n.stack));
+
+// Test prepareStackTrace
+
+assertEquals(undefined, Error.prepareStackTrace);
+
+var prepareCalled = false;
+
+function diagnoseStack(err, stack) {
+ var s = '';
+ prepareCalled = true;
+ stack.forEach(function (e) {
+ assertEquals('object', typeof e);
+ s += e.getFunctionName() + ' ';
+ s += e.getMethodName() + ' ';
+ s += e.getFileName() + ' ';
+ s += e.getLineNumber() + ' ';
+ s += '\n';
+ });
+ return s;
+}
+Error.prepareStackTrace = diagnoseStack;
+
+var s1 = {};
+grandParentCapture(s1);
+assertTrue(/nestedCapture/.test(s1.stack));
+assertTrue(/parentCapture/.test(s1.stack));
+assertTrue(/grandParentCapture/.test(s1.stack));
+assertTrue(prepareCalled);
+
+// Test that it is limited by the function flag as above
+
+var s2 = {};
+grandParentCapture(s2, parentCapture);
+assertFalse(/nestedCapture/.test(s2.stack));
+assertFalse(/parentCapture/.test(s2.stack));
+assertTrue(/grandParentCapture/.test(s2.stack));
+
+// Test that it all works on a throw. Note that the error text isn't included.
+
+try {
+ grandparentThrower('Custom 1');
+} catch (e) {
+ assertFalse(/Custom 1/.test(e.stack));
+ assertTrue(/nestedThrower/.test(e.stack));
+ assertTrue(/parentThrower/.test(e.stack));
+ assertTrue(/grandparentThrower/.test(e.stack));
+}
+
+// And test that it works the old way when we format it back
+Error.prepareStackTrace = undefined;
+
+try {
+ grandparentThrower('Custom 2');
+} catch (e) {
+ assertFalse(/Custom 2/.test(e.stack));
+ assertTrue(/nestedThrower/.test(e.stack));
+ assertTrue(/parentThrower/.test(e.stack));
+ assertTrue(/grandparentThrower/.test(e.stack));
+}
+
+// test that all the functions on a stack frame work
+
+function printFrame(l, f) {
+ var o =
+ {typeofThis: typeof f.getThis(),
+ typeName: f.getTypeName(),
+ function: f.getFunction(),
+ functionName: f.getFunctionName(),
+ methodName: f.getMethodName(),
+ fileName: f.getFileName(),
+ lineNumber: f.getLineNumber(),
+ columnNumber: f.getColumnNumber(),
+ evalOrigin: f.getEvalOrigin(),
+ topLevel: f.isToplevel(),
+ eval: f.isEval(),
+ native: f.isNative(),
+ constructor: f.isConstructor()
+ };
+
+ l.push(o);
+ return l;
+}
+
+Error.prepareStackTrace = function (e, frames) {
+ return frames.reduce(printFrame, []);
+};
+
+try {
+ grandparentThrower('testing stack');
+} catch (e) {
+ e.stack.forEach(function (f) {
+ verifyFrame(f);
+ });
+}
+
+function verifyFrame(f) {
+ assertEquals(typeof f.fileName, 'string');
+ assertEquals(typeof f.lineNumber, 'number');
+ assertEquals(typeof f.topLevel, 'boolean');
+ assertEquals(typeof f.eval, 'boolean');
+ assertEquals(typeof f.native, 'boolean');
+ assertEquals(typeof f.constructor, 'boolean');
+}
diff --git a/testsrc/jstests/extensions/stack-traces.js b/testsrc/jstests/extensions/stack-traces-v8.js
similarity index 95%
rename from testsrc/jstests/extensions/stack-traces.js
rename to testsrc/jstests/extensions/stack-traces-v8.js
index f99602fab5..136cfd8a5e 100644
--- a/testsrc/jstests/extensions/stack-traces.js
+++ b/testsrc/jstests/extensions/stack-traces-v8.js
@@ -36,9 +36,9 @@ try {
} catch (e) {
assertFalse(e.stack == undefined);
assertTrue(/Test 1/.test(e.toString()));
- assertFalse(/stack-traces.js/.test(e.toString()));
+ assertFalse(/stack-traces-v8.js/.test(e.toString()));
assertTrue(/Test 1/.test(e.stack));
- assertTrue(/stack-traces.js/.test(e.stack));
+ assertTrue(/stack-traces-v8.js/.test(e.stack));
}
// Assert that the function name is nested inside a nested stack trace
@@ -167,8 +167,10 @@ assertTrue(/grandParentCapture/.test(s2.stack));
try {
grandparentThrower('Custom 1');
} catch (e) {
+ assertFalse(/Custom 1/.test(e.stack));
assertTrue(/nestedThrower/.test(e.stack));
assertTrue(/parentThrower/.test(e.stack));
+ assertTrue(/grandparentThrower/.test(e.stack));
}
// And test that it works the old way when we format it back
@@ -180,6 +182,7 @@ try {
assertTrue(/Custom 2/.test(e.stack));
assertTrue(/nestedThrower/.test(e.stack));
assertTrue(/parentThrower/.test(e.stack));
+ assertTrue(/grandparentThrower/.test(e.stack));
}
// test that all the functions on a stack frame work
diff --git a/testsrc/org/mozilla/javascript/tests/StackTraceExtensionMozillaLfTest.java b/testsrc/org/mozilla/javascript/tests/StackTraceExtensionMozillaLfTest.java
new file mode 100644
index 0000000000..b6c6aae3cc
--- /dev/null
+++ b/testsrc/org/mozilla/javascript/tests/StackTraceExtensionMozillaLfTest.java
@@ -0,0 +1,80 @@
+package org.mozilla.javascript.tests;
+
+import static org.junit.Assert.assertFalse;
+
+import java.io.FileReader;
+import java.io.IOException;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.ContextFactory;
+import org.mozilla.javascript.RhinoException;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.StackStyle;
+import org.mozilla.javascript.tools.shell.Global;
+
+public class StackTraceExtensionMozillaLfTest {
+ @BeforeClass
+ public static void init() {
+ RhinoException.setStackStyle(StackStyle.MOZILLA);
+ }
+
+ @AfterClass
+ public static void terminate() {
+ RhinoException.setStackStyle(StackStyle.RHINO);
+ }
+
+ private void testTraces(int opt) {
+ final ContextFactory factory =
+ new ContextFactory() {
+ @Override
+ protected boolean hasFeature(Context cx, int featureIndex) {
+ switch (featureIndex) {
+ case Context.FEATURE_LOCATION_INFORMATION_IN_ERROR:
+ return true;
+ default:
+ return super.hasFeature(cx, featureIndex);
+ }
+ }
+ };
+
+ Context cx = factory.enterContext();
+ try {
+ cx.setLanguageVersion(Context.VERSION_1_8);
+ cx.setOptimizationLevel(opt);
+ cx.setGeneratingDebug(true);
+
+ Global global = new Global(cx);
+ Scriptable root = cx.newObject(global);
+
+ FileReader rdr =
+ new FileReader("testsrc/jstests/extensions/stack-traces-mozilla-lf.js");
+
+ try {
+ cx.evaluateReader(root, rdr, "stack-traces-mozilla-lf.js", 1, null);
+ } finally {
+ rdr.close();
+ }
+ } catch (IOException ioe) {
+ assertFalse("I/O Error: " + ioe, true);
+ } finally {
+ Context.exit();
+ }
+ }
+
+ @Test
+ public void testStackTrace0() {
+ testTraces(0);
+ }
+
+ @Test
+ public void testStackTrace9() {
+ testTraces(9);
+ }
+
+ @Test
+ public void testStackTraceInt() {
+ testTraces(-1);
+ }
+}
diff --git a/testsrc/org/mozilla/javascript/tests/StackTraceExtensionMozillaTest.java b/testsrc/org/mozilla/javascript/tests/StackTraceExtensionMozillaTest.java
new file mode 100644
index 0000000000..f4afb6724d
--- /dev/null
+++ b/testsrc/org/mozilla/javascript/tests/StackTraceExtensionMozillaTest.java
@@ -0,0 +1,79 @@
+package org.mozilla.javascript.tests;
+
+import static org.junit.Assert.assertFalse;
+
+import java.io.FileReader;
+import java.io.IOException;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.ContextFactory;
+import org.mozilla.javascript.RhinoException;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.StackStyle;
+import org.mozilla.javascript.tools.shell.Global;
+
+public class StackTraceExtensionMozillaTest {
+ @BeforeClass
+ public static void init() {
+ RhinoException.setStackStyle(StackStyle.MOZILLA);
+ }
+
+ @AfterClass
+ public static void terminate() {
+ RhinoException.setStackStyle(StackStyle.RHINO);
+ }
+
+ private void testTraces(int opt) {
+ final ContextFactory factory =
+ new ContextFactory() {
+ @Override
+ protected boolean hasFeature(Context cx, int featureIndex) {
+ switch (featureIndex) {
+ case Context.FEATURE_LOCATION_INFORMATION_IN_ERROR:
+ return true;
+ default:
+ return super.hasFeature(cx, featureIndex);
+ }
+ }
+ };
+
+ Context cx = factory.enterContext();
+ try {
+ cx.setLanguageVersion(Context.VERSION_1_8);
+ cx.setOptimizationLevel(opt);
+ cx.setGeneratingDebug(true);
+
+ Global global = new Global(cx);
+ Scriptable root = cx.newObject(global);
+
+ FileReader rdr = new FileReader("testsrc/jstests/extensions/stack-traces-mozilla.js");
+
+ try {
+ cx.evaluateReader(root, rdr, "stack-traces-mozilla.js", 1, null);
+ } finally {
+ rdr.close();
+ }
+ } catch (IOException ioe) {
+ assertFalse("I/O Error: " + ioe, true);
+ } finally {
+ Context.exit();
+ }
+ }
+
+ @Test
+ public void testStackTrace0() {
+ testTraces(0);
+ }
+
+ @Test
+ public void testStackTrace9() {
+ testTraces(9);
+ }
+
+ @Test
+ public void testStackTraceInt() {
+ testTraces(-1);
+ }
+}
diff --git a/testsrc/org/mozilla/javascript/tests/StackTraceExtensionRhinoTest.java b/testsrc/org/mozilla/javascript/tests/StackTraceExtensionRhinoTest.java
new file mode 100644
index 0000000000..e003fbf2f5
--- /dev/null
+++ b/testsrc/org/mozilla/javascript/tests/StackTraceExtensionRhinoTest.java
@@ -0,0 +1,65 @@
+package org.mozilla.javascript.tests;
+
+import static org.junit.Assert.assertFalse;
+
+import java.io.FileReader;
+import java.io.IOException;
+import org.junit.Test;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.ContextFactory;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.tools.shell.Global;
+
+public class StackTraceExtensionRhinoTest {
+ private void testTraces(int opt) {
+ final ContextFactory factory =
+ new ContextFactory() {
+ @Override
+ protected boolean hasFeature(Context cx, int featureIndex) {
+ switch (featureIndex) {
+ case Context.FEATURE_LOCATION_INFORMATION_IN_ERROR:
+ return true;
+ default:
+ return super.hasFeature(cx, featureIndex);
+ }
+ }
+ };
+
+ Context cx = factory.enterContext();
+ try {
+ cx.setLanguageVersion(Context.VERSION_1_8);
+ cx.setOptimizationLevel(opt);
+ cx.setGeneratingDebug(true);
+
+ Global global = new Global(cx);
+ Scriptable root = cx.newObject(global);
+
+ FileReader rdr = new FileReader("testsrc/jstests/extensions/stack-traces-rhino.js");
+
+ try {
+ cx.evaluateReader(root, rdr, "stack-traces-rhino.js", 1, null);
+ } finally {
+ rdr.close();
+ }
+ } catch (IOException ioe) {
+ assertFalse("I/O Error: " + ioe, true);
+ } finally {
+ Context.exit();
+ }
+ }
+
+ @Test
+ public void testStackTrace0() {
+ testTraces(0);
+ }
+
+ @Test
+ public void testStackTrace9() {
+ testTraces(9);
+ }
+
+ @Test
+ public void testStackTraceInt() {
+ testTraces(-1);
+ }
+}
diff --git a/testsrc/org/mozilla/javascript/tests/StackTraceExtensionTest.java b/testsrc/org/mozilla/javascript/tests/StackTraceExtensionV8Test.java
similarity index 60%
rename from testsrc/org/mozilla/javascript/tests/StackTraceExtensionTest.java
rename to testsrc/org/mozilla/javascript/tests/StackTraceExtensionV8Test.java
index f94303b249..57a6741ac4 100644
--- a/testsrc/org/mozilla/javascript/tests/StackTraceExtensionTest.java
+++ b/testsrc/org/mozilla/javascript/tests/StackTraceExtensionV8Test.java
@@ -4,7 +4,6 @@
import java.io.FileReader;
import java.io.IOException;
-
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -15,34 +14,30 @@
import org.mozilla.javascript.StackStyle;
import org.mozilla.javascript.tools.shell.Global;
-public class StackTraceExtensionTest
-{
+public class StackTraceExtensionV8Test {
@BeforeClass
- public static void init()
- {
+ public static void init() {
RhinoException.setStackStyle(StackStyle.V8);
}
@AfterClass
- public static void terminate()
- {
+ public static void terminate() {
RhinoException.setStackStyle(StackStyle.RHINO);
}
- private void testTraces(int opt)
- {
- final ContextFactory factory = new ContextFactory() {
- @Override
- protected boolean hasFeature(Context cx, int featureIndex)
- {
- switch (featureIndex) {
- case Context.FEATURE_LOCATION_INFORMATION_IN_ERROR:
- return true;
- default:
- return super.hasFeature(cx, featureIndex);
- }
- }
- };
+ private void testTraces(int opt) {
+ final ContextFactory factory =
+ new ContextFactory() {
+ @Override
+ protected boolean hasFeature(Context cx, int featureIndex) {
+ switch (featureIndex) {
+ case Context.FEATURE_LOCATION_INFORMATION_IN_ERROR:
+ return true;
+ default:
+ return super.hasFeature(cx, featureIndex);
+ }
+ }
+ };
Context cx = factory.enterContext();
try {
@@ -53,10 +48,10 @@ protected boolean hasFeature(Context cx, int featureIndex)
Global global = new Global(cx);
Scriptable root = cx.newObject(global);
- FileReader rdr = new FileReader("testsrc/jstests/extensions/stack-traces.js");
+ FileReader rdr = new FileReader("testsrc/jstests/extensions/stack-traces-v8.js");
try {
- cx.evaluateReader(root, rdr, "stack-traces.js", 1, null);
+ cx.evaluateReader(root, rdr, "stack-traces-v8.js", 1, null);
} finally {
rdr.close();
}
@@ -68,20 +63,17 @@ protected boolean hasFeature(Context cx, int featureIndex)
}
@Test
- public void testStackTrace0()
- {
+ public void testStackTrace0() {
testTraces(0);
}
@Test
- public void testStackTrace9()
- {
+ public void testStackTrace9() {
testTraces(9);
}
@Test
- public void testStackTraceInt()
- {
+ public void testStackTraceInt() {
testTraces(-1);
}
}
diff --git a/testsrc/org/mozilla/javascript/tests/StackTraceTest.java b/testsrc/org/mozilla/javascript/tests/StackTraceTest.java
index 358ed96565..b6f0c1220c 100644
--- a/testsrc/org/mozilla/javascript/tests/StackTraceTest.java
+++ b/testsrc/org/mozilla/javascript/tests/StackTraceTest.java
@@ -2,52 +2,125 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-/**
- *
- */
+/** */
package org.mozilla.javascript.tests;
+import junit.framework.TestCase;
import org.mozilla.javascript.JavaScriptException;
import org.mozilla.javascript.RhinoException;
import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.StackStyle;
-import junit.framework.TestCase;
-
-/**
- * @author Marc Guillemot
- */
+/** @author Marc Guillemot */
public class StackTraceTest extends TestCase {
- final static String LS = System.getProperty("line.separator");
+ static final String LS = System.getProperty("line.separator");
+
+ /**
+ * As of CVS head on May, 11. 2009, stacktrace information is lost when a call to some native
+ * function has been made.
+ */
+ public void testFailureStackTraceRhino() {
+ final StackStyle stackStyle = RhinoException.getStackStyle();
+ try {
+ RhinoException.setStackStyle(StackStyle.RHINO);
+
+ final String source1 = "function f2() { throw 'hello'; }; f2();";
+ final String source2 = "function f2() { 'H'.toLowerCase(); throw 'hello'; }; f2();";
+ final String source3 =
+ "function f2() { new java.lang.String('H').toLowerCase(); throw 'hello'; }; f2();";
+ final String result = "\tat test.js (f2)" + LS + "\tat test.js" + LS;
+
+ runWithExpectedStackTrace(source1, result);
+ runWithExpectedStackTrace(source2, result);
+ runWithExpectedStackTrace(source3, result);
+ } finally {
+ RhinoException.setStackStyle(stackStyle);
+ }
+ }
/**
- * As of CVS head on May, 11. 2009, stacktrace information is lost when a call to some
- * native function has been made.
+ * As of CVS head on May, 11. 2009, stacktrace information is lost when a call to some native
+ * function has been made.
*/
- public void testFailureStackTrace() {
- RhinoException.useMozillaStackStyle(false);
- final String source1 = "function f2() { throw 'hello'; }; f2();";
- final String source2 = "function f2() { 'H'.toLowerCase(); throw 'hello'; }; f2();";
- final String source3 = "function f2() { new java.lang.String('H').toLowerCase(); throw 'hello'; }; f2();";
- final String result = "\tat test.js (f2)" + LS + "\tat test.js" + LS;
-
- runWithExpectedStackTrace(source1, result);
- runWithExpectedStackTrace(source2, result);
- runWithExpectedStackTrace(source3, result);
+ public void testFailureStackTraceMozilla() {
+ final StackStyle stackStyle = RhinoException.getStackStyle();
+ try {
+ RhinoException.setStackStyle(StackStyle.MOZILLA);
+
+ final String source1 = "function f2() { throw 'hello'; }; f2();";
+ final String source2 = "function f2() { 'H'.toLowerCase(); throw 'hello'; }; f2();";
+ final String source3 =
+ "function f2() { new java.lang.String('H').toLowerCase(); throw 'hello'; }; f2();";
+ final String result = "f2()@test.js" + LS + "@test.js" + LS;
+
+ runWithExpectedStackTrace(source1, result);
+ runWithExpectedStackTrace(source2, result);
+ runWithExpectedStackTrace(source3, result);
+ } finally {
+ RhinoException.setStackStyle(stackStyle);
+ }
+ }
+
+ /**
+ * As of CVS head on May, 11. 2009, stacktrace information is lost when a call to some native
+ * function has been made.
+ */
+ public void testFailureStackTraceMozillaLf() {
+ final StackStyle stackStyle = RhinoException.getStackStyle();
+ try {
+ RhinoException.setStackStyle(StackStyle.MOZILLA_LF);
+
+ final String source1 = "function f2() { throw 'hello'; }; f2();";
+ final String source2 = "function f2() { 'H'.toLowerCase(); throw 'hello'; }; f2();";
+ final String source3 =
+ "function f2() { new java.lang.String('H').toLowerCase(); throw 'hello'; }; f2();";
+ final String result = "f2()@test.js\n@test.js\n";
+
+ runWithExpectedStackTrace(source1, result);
+ runWithExpectedStackTrace(source2, result);
+ runWithExpectedStackTrace(source3, result);
+ } finally {
+ RhinoException.setStackStyle(stackStyle);
+ }
+ }
+
+ /**
+ * As of CVS head on May, 11. 2009, stacktrace information is lost when a call to some native
+ * function has been made.
+ */
+ public void testFailureStackTraceV8() {
+ final StackStyle stackStyle = RhinoException.getStackStyle();
+ try {
+ RhinoException.setStackStyle(StackStyle.V8);
+
+ final String source1 = "function f2() { throw 'hello'; }; f2();";
+ final String source2 = "function f2() { 'H'.toLowerCase(); throw 'hello'; }; f2();";
+ final String source3 =
+ "function f2() { new java.lang.String('H').toLowerCase(); throw 'hello'; }; f2();";
+ final String result =
+ "hello" + LS + " at f2 (test.js:0:0)" + LS + " at test.js:0:0" + LS;
+
+ runWithExpectedStackTrace(source1, result);
+ runWithExpectedStackTrace(source2, result);
+ runWithExpectedStackTrace(source3, result);
+ } finally {
+ RhinoException.setStackStyle(stackStyle);
+ }
}
- private void runWithExpectedStackTrace(final String _source, final String _expectedStackTrace)
- {
- Utils.runWithOptimizationLevel(cx -> {
- final Scriptable scope = cx.initStandardObjects();
- try {
- cx.evaluateString(scope, _source, "test.js", 0, null);
- }
- catch (final JavaScriptException e)
- {
- assertEquals(_expectedStackTrace, e.getScriptStackTrace());
- return null;
- }
- throw new RuntimeException("Exception expected!");
- }, -1);
+ private static void runWithExpectedStackTrace(
+ final String _source, final String _expectedStackTrace) {
+ Utils.runWithOptimizationLevel(
+ cx -> {
+ final Scriptable scope = cx.initStandardObjects();
+ try {
+ cx.evaluateString(scope, _source, "test.js", 0, null);
+ } catch (final JavaScriptException e) {
+ assertEquals(_expectedStackTrace, e.getScriptStackTrace());
+ return null;
+ }
+ throw new RuntimeException("Exception expected!");
+ },
+ -1);
}
- }
+}