mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-15 18:33:41 +00:00
8014781: support Error.captureStackTrace
Reviewed-by: jlaskey, hannesw
This commit is contained in:
parent
70383eb20a
commit
ee8b3bd823
@ -25,6 +25,9 @@
|
||||
|
||||
package jdk.nashorn.api.scripting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import jdk.nashorn.internal.codegen.CompilerConstants;
|
||||
import jdk.nashorn.internal.runtime.ECMAErrors;
|
||||
|
||||
/**
|
||||
@ -136,4 +139,52 @@ public abstract class NashornException extends RuntimeException {
|
||||
return column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array javascript stack frames from the given exception object.
|
||||
*
|
||||
* @param exception exception from which stack frames are retrieved and filtered
|
||||
* @return array of javascript stack frames
|
||||
*/
|
||||
public static StackTraceElement[] getScriptFrames(final Throwable exception) {
|
||||
final StackTraceElement[] frames = ((Throwable)exception).getStackTrace();
|
||||
final List<StackTraceElement> filtered = new ArrayList<>();
|
||||
for (final StackTraceElement st : frames) {
|
||||
if (ECMAErrors.isScriptFrame(st)) {
|
||||
final String className = "<" + st.getFileName() + ">";
|
||||
String methodName = st.getMethodName();
|
||||
if (methodName.equals(CompilerConstants.RUN_SCRIPT.symbolName())) {
|
||||
methodName = "<program>";
|
||||
}
|
||||
filtered.add(new StackTraceElement(className, methodName,
|
||||
st.getFileName(), st.getLineNumber()));
|
||||
}
|
||||
}
|
||||
return filtered.toArray(new StackTraceElement[filtered.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a formatted script stack trace string with frames information separated by '\n'
|
||||
*
|
||||
* @param exception exception for which script stack string is returned
|
||||
* @return formatted stack trace string
|
||||
*/
|
||||
public static String getScriptStackString(final Throwable exception) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
final StackTraceElement[] frames = getScriptFrames((Throwable)exception);
|
||||
for (final StackTraceElement st : frames) {
|
||||
buf.append(st.getMethodName());
|
||||
buf.append(" @ ");
|
||||
buf.append(st.getFileName());
|
||||
buf.append(':');
|
||||
buf.append(st.getLineNumber());
|
||||
buf.append('\n');
|
||||
}
|
||||
final int len = buf.length();
|
||||
// remove trailing '\n'
|
||||
if (len > 0) {
|
||||
assert buf.charAt(len - 1) == '\n';
|
||||
buf.deleteCharAt(len - 1);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@ import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import jdk.nashorn.api.scripting.NashornException;
|
||||
import jdk.nashorn.internal.codegen.CompilerConstants;
|
||||
import jdk.nashorn.internal.lookup.MethodHandleFactory;
|
||||
import jdk.nashorn.internal.objects.annotations.Attribute;
|
||||
@ -118,6 +119,20 @@ public final class NativeError extends ScriptObject {
|
||||
return new NativeError(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Nashorn extension: Error.captureStackTrace. Capture stack trace at the point of call into the Error object provided.
|
||||
*
|
||||
* @param self self reference
|
||||
*/
|
||||
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
|
||||
public static Object captureStackTrace(final Object self, final Object errorObj) {
|
||||
Global.checkObject(errorObj);
|
||||
final ScriptObject sobj = (ScriptObject)errorObj;
|
||||
final ECMAException exp = new ECMAException(sobj, null);
|
||||
sobj.set("stack", NashornException.getScriptStackString(exp), false);
|
||||
return UNDEFINED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nashorn extension: Error.dumpStack
|
||||
* dumps the stack of the current thread.
|
||||
@ -163,7 +178,7 @@ public final class NativeError extends ScriptObject {
|
||||
final Object exception = ECMAException.getException(sobj);
|
||||
Object[] res;
|
||||
if (exception instanceof Throwable) {
|
||||
res = getScriptFrames((Throwable)exception);
|
||||
res = NashornException.getScriptFrames((Throwable)exception);
|
||||
} else {
|
||||
res = ScriptRuntime.EMPTY_ARRAY;
|
||||
}
|
||||
@ -272,25 +287,8 @@ public final class NativeError extends ScriptObject {
|
||||
}
|
||||
|
||||
final Object exception = ECMAException.getException(sobj);
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
if (exception instanceof Throwable) {
|
||||
final Object[] frames = getScriptFrames((Throwable)exception);
|
||||
for (final Object fr : frames) {
|
||||
final StackTraceElement st = (StackTraceElement)fr;
|
||||
buf.append(st.getMethodName());
|
||||
buf.append(" @ ");
|
||||
buf.append(st.getFileName());
|
||||
buf.append(':');
|
||||
buf.append(st.getLineNumber());
|
||||
buf.append('\n');
|
||||
}
|
||||
final int len = buf.length();
|
||||
// remove trailing '\n'
|
||||
if (len > 0) {
|
||||
assert buf.charAt(len - 1) == '\n';
|
||||
buf.deleteCharAt(len - 1);
|
||||
}
|
||||
return buf.toString();
|
||||
return NashornException.getScriptStackString((Throwable)exception);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
@ -364,21 +362,4 @@ public final class NativeError extends ScriptObject {
|
||||
throw new MethodHandleFactory.LookupException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Object[] getScriptFrames(final Throwable exception) {
|
||||
final StackTraceElement[] frames = ((Throwable)exception).getStackTrace();
|
||||
final List<StackTraceElement> filtered = new ArrayList<>();
|
||||
for (final StackTraceElement st : frames) {
|
||||
if (ECMAErrors.isScriptFrame(st)) {
|
||||
final String className = "<" + st.getFileName() + ">";
|
||||
String methodName = st.getMethodName();
|
||||
if (methodName.equals(CompilerConstants.RUN_SCRIPT.symbolName())) {
|
||||
methodName = "<program>";
|
||||
}
|
||||
filtered.add(new StackTraceElement(className, methodName,
|
||||
st.getFileName(), st.getLineNumber()));
|
||||
}
|
||||
}
|
||||
return filtered.toArray();
|
||||
}
|
||||
}
|
||||
|
||||
40
nashorn/test/script/basic/JDK-8014781.js
Normal file
40
nashorn/test/script/basic/JDK-8014781.js
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8014781: support Error.captureStackTrace
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
function MyError() {
|
||||
Error.captureStackTrace(this);
|
||||
}
|
||||
|
||||
function func() {
|
||||
return new MyError();
|
||||
}
|
||||
|
||||
var e = func();
|
||||
print(e.stack.replace(/\\/g, '/'));
|
||||
3
nashorn/test/script/basic/JDK-8014781.js.EXPECTED
Normal file
3
nashorn/test/script/basic/JDK-8014781.js.EXPECTED
Normal file
@ -0,0 +1,3 @@
|
||||
MyError @ test/script/basic/JDK-8014781.js:32
|
||||
func @ test/script/basic/JDK-8014781.js:36
|
||||
<program> @ test/script/basic/JDK-8014781.js:39
|
||||
Loading…
x
Reference in New Issue
Block a user