src/jdk/nashorn/internal/runtime/ECMAException.java
Print this page
@@ -23,18 +23,19 @@
* questions.
*/
package jdk.nashorn.internal.runtime;
-import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
import static jdk.nashorn.internal.codegen.CompilerConstants.virtualField;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import javax.script.ScriptException;
import jdk.nashorn.api.scripting.NashornException;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
import jdk.nashorn.internal.codegen.CompilerConstants.FieldAccess;
+import jdk.nashorn.internal.objects.NativeError;
/**
* Exception used to implement ECMAScript "throw" from scripts. The actual thrown
* object from script need not be a Java exception and so it is wrapped as an
* instance field called "thrown" here. This exception class is also used to
@@ -42,40 +43,38 @@
* ReferenceError thrown from Nashorn engine runtime).
*/
@SuppressWarnings("serial")
public final class ECMAException extends NashornException {
/**
- * Method handle pointing to the constructor {@link ECMAException#ECMAException(Object, String, int, int)},
+ * Method handle pointing to the constructor {@link ECMAException#create(Object, String, int, int)},
*/
- public static final Call THROW_INIT = constructorNoLookup(ECMAException.class, Object.class, String.class, int.class, int.class);
+ public static final Call CREATE = staticCallNoLookup(ECMAException.class, "create", ECMAException.class, Object.class, String.class, int.class, int.class);
/** Field handle to the{@link ECMAException#thrown} field, so that it can be accessed from generated code */
public static final FieldAccess THROWN = virtualField(ECMAException.class, "thrown", Object.class);
private static final String EXCEPTION_PROPERTY = "nashornException";
/** Object thrown. */
public final Object thrown;
/**
- * Constructor. This is called from generated code to implement the {@code throw}
- * instruction from generated script code
+ * Constructor. Called from the factory method 'create'.
*
* @param thrown object to be thrown
* @param fileName script file name
* @param line line number of throw
* @param column column number of throw
*/
- public ECMAException(final Object thrown, final String fileName, final int line, final int column) {
+ private ECMAException(final Object thrown, final String fileName, final int line, final int column) {
super(ScriptRuntime.safeToString(thrown), asThrowable(thrown), fileName, line, column);
this.thrown = thrown;
setExceptionToThrown();
}
/**
- * Constructor. This is called from runtime code in Nashorn to throw things like
- * type errors.
+ * Constructor. This is called from the runtime code.
*
* @param thrown object to be thrown
* @param cause Java exception that triggered this throw
*/
public ECMAException(final Object thrown, final Throwable cause) {
@@ -83,10 +82,39 @@
this.thrown = thrown;
setExceptionToThrown();
}
/**
+ * Factory method to retrieve the underlying exception or create an exception.
+ * This method is called from the generated code.
+ *
+ * @param thrown object to be thrown
+ * @param fileName script file name
+ * @param line line number of throw
+ * @param column column number of throw
+ * @return ECMAException object
+ */
+ public static ECMAException create(final Object thrown, final String fileName, final int line, final int column) {
+ // If thrown object is an Error or sub-object like TypeError, then
+ // an ECMAException object has been already initialized at constructor.
+ if (thrown instanceof ScriptObject) {
+ ScriptObject sobj = (ScriptObject)thrown;
+ Object exception = getException(sobj);
+ if (exception instanceof ECMAException) {
+ // copy over file name, line number and column number.
+ final ECMAException ee = (ECMAException)exception;
+ ee.setFileName(fileName);
+ ee.setLineNumber(line);
+ ee.setColumnNumber(column);
+ return ee;
+ }
+ }
+
+ return new ECMAException(thrown, fileName, line, column);
+ }
+
+ /**
* Get the thrown object
* @return thrown object
*/
@Override
public Object getThrown() {
@@ -255,9 +283,11 @@
if (thrown instanceof ScriptObject) {
final ScriptObject sobj = (ScriptObject)thrown;
if (!sobj.has(EXCEPTION_PROPERTY)) {
sobj.addOwnProperty(EXCEPTION_PROPERTY, Property.NOT_ENUMERABLE, this);
+ } else {
+ sobj.set(EXCEPTION_PROPERTY, this, false);
}
}
}
}