# HG changeset patch # User asaha # Date 1389937577 28800 # Node ID f73a809e4b06bebace6f41de2c6ddb9439aba8eb # Parent 9d430eab0c443700424345cf193306c8352041c8# Parent 1a18a66a182f96db1e05b021f79995b30897b859 Merge diff -r 9d430eab0c44 -r f73a809e4b06 nashorn/src/jdk/nashorn/api/scripting/NashornException.java --- a/nashorn/src/jdk/nashorn/api/scripting/NashornException.java Wed Jan 15 10:24:42 2014 -0800 +++ b/nashorn/src/jdk/nashorn/api/scripting/NashornException.java Thu Jan 16 21:46:17 2014 -0800 @@ -45,11 +45,11 @@ @SuppressWarnings("serial") public abstract class NashornException extends RuntimeException { // script file name - private final String fileName; + private String fileName; // script line number - private final int line; + private int line; // script column number - private final int column; + private int column; // underlying ECMA error object - lazily initialized private Object ecmaError; @@ -125,6 +125,15 @@ } /** + * Set the source file name for this {@code NashornException} + * + * @param fileName the file name + */ + public final void setFileName(final String fileName) { + this.fileName = fileName; + } + + /** * Get the line number for this {@code NashornException} * * @return the line number @@ -134,15 +143,33 @@ } /** + * Set the line number for this {@code NashornException} + * + * @param line the line number + */ + public final void setLineNumber(final int line) { + this.line = line; + } + + /** * Get the column for this {@code NashornException} * - * @return the column + * @return the column number */ public final int getColumnNumber() { return column; } /** + * Set the column for this {@code NashornException} + * + * @param column the column number + */ + public final void setColumnNumber(final int column) { + this.column = column; + } + + /** * Returns array javascript stack frames from the given exception object. * * @param exception exception from which stack frames are retrieved and filtered @@ -208,9 +235,9 @@ final Object thrown = getThrown(); if (thrown instanceof ScriptObject) { - ecmaError = ScriptObjectMirror.wrap(thrown, global); + setEcmaError(ScriptObjectMirror.wrap(thrown, global)); } else { - ecmaError = thrown; + setEcmaError(thrown); } return this; @@ -225,4 +252,14 @@ public Object getEcmaError() { return ecmaError; } + + /** + * Return the underlying ECMA error object, if available. + * + * @param ecmaError underlying ECMA Error object's mirror or whatever was thrown + * from script such as a String, Number or a Boolean. + */ + public void setEcmaError(final Object ecmaError) { + this.ecmaError = ecmaError; + } } diff -r 9d430eab0c44 -r f73a809e4b06 nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java --- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Jan 15 10:24:42 2014 -0800 +++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Jan 16 21:46:17 2014 -0800 @@ -2023,8 +2023,6 @@ return false; } - method._new(ECMAException.class).dup(); - final Source source = lc.getCurrentFunction().getSource(); final Expression expression = throwNode.getExpression(); @@ -2037,7 +2035,7 @@ method.load(source.getName()); method.load(line); method.load(column); - method.invoke(ECMAException.THROW_INIT); + method.invoke(ECMAException.CREATE); method.athrow(); diff -r 9d430eab0c44 -r f73a809e4b06 nashorn/src/jdk/nashorn/internal/objects/NativeError.java --- a/nashorn/src/jdk/nashorn/internal/objects/NativeError.java Wed Jan 15 10:24:42 2014 -0800 +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeError.java Thu Jan 16 21:46:17 2014 -0800 @@ -38,7 +38,6 @@ import jdk.nashorn.internal.objects.annotations.Property; import jdk.nashorn.internal.objects.annotations.ScriptClass; import jdk.nashorn.internal.objects.annotations.Where; -import jdk.nashorn.internal.objects.ScriptFunctionImpl; import jdk.nashorn.internal.runtime.ECMAException; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.PropertyMap; @@ -75,7 +74,7 @@ static final String FILENAME = "__fileName__"; /** Message property name */ - @Property(name = NativeError.MESSAGE) + @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE) public Object instMessage; /** ECMA 15.11.4.2 Error.prototype.name */ @@ -93,6 +92,7 @@ return $nasgenmap$; } + @SuppressWarnings("LeakingThisInConstructor") private NativeError(final Object msg, final ScriptObject proto, final PropertyMap map) { super(proto, map); if (msg != UNDEFINED) { @@ -100,6 +100,7 @@ } else { this.delete(NativeError.MESSAGE, false); } + initException(this); } NativeError(final Object msg, final Global global) { @@ -129,6 +130,14 @@ return new NativeError(msg); } + // This is called NativeError, NativeTypeError etc. to + // associate a ECMAException with the ECMA Error object. + @SuppressWarnings("unused") + static void initException(final ScriptObject self) { + // ECMAException constructor has side effects + new ECMAException(self, null); + } + /** * Nashorn extension: Error.captureStackTrace. Capture stack trace at the point of call into the Error object provided. * @@ -136,16 +145,17 @@ * @param errorObj the error object * @return undefined */ - @SuppressWarnings("unused") @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; - new ECMAException(sobj, null); //constructor has side effects - sobj.delete("stack", false); - final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", GET_STACK); - final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", SET_STACK); - sobj.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack); + initException(sobj); + sobj.delete(STACK, false); + if (! sobj.has("stack")) { + final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", GET_STACK); + final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", SET_STACK); + sobj.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack); + } return UNDEFINED; } @@ -226,7 +236,11 @@ public static Object setLineNumber(final Object self, final Object value) { Global.checkObject(self); final ScriptObject sobj = (ScriptObject)self; - sobj.set(LINENUMBER, value, false); + if (sobj.hasOwnProperty(LINENUMBER)) { + sobj.put(LINENUMBER, value, false); + } else { + sobj.addOwnProperty(LINENUMBER, Attribute.NOT_ENUMERABLE, value); + } return value; } @@ -254,7 +268,11 @@ public static Object setColumnNumber(final Object self, final Object value) { Global.checkObject(self); final ScriptObject sobj = (ScriptObject)self; - sobj.set(COLUMNNUMBER, value, false); + if (sobj.hasOwnProperty(COLUMNNUMBER)) { + sobj.put(COLUMNNUMBER, value, false); + } else { + sobj.addOwnProperty(COLUMNNUMBER, Attribute.NOT_ENUMERABLE, value); + } return value; } @@ -282,7 +300,11 @@ public static Object setFileName(final Object self, final Object value) { Global.checkObject(self); final ScriptObject sobj = (ScriptObject)self; - sobj.set(FILENAME, value, false); + if (sobj.hasOwnProperty(FILENAME)) { + sobj.put(FILENAME, value, false); + } else { + sobj.addOwnProperty(FILENAME, Attribute.NOT_ENUMERABLE, value); + } return value; } @@ -304,10 +326,12 @@ final Object exception = ECMAException.getException(sobj); if (exception instanceof Throwable) { - return getScriptStackString(sobj, (Throwable)exception); + Object value = getScriptStackString(sobj, (Throwable)exception); + sobj.put(STACK, value, false); + return value; } - return ""; + return UNDEFINED; } /** diff -r 9d430eab0c44 -r f73a809e4b06 nashorn/src/jdk/nashorn/internal/objects/NativeEvalError.java --- a/nashorn/src/jdk/nashorn/internal/objects/NativeEvalError.java Wed Jan 15 10:24:42 2014 -0800 +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeEvalError.java Thu Jan 16 21:46:17 2014 -0800 @@ -44,7 +44,7 @@ public final class NativeEvalError extends ScriptObject { /** message property in instance */ - @Property(name = NativeError.MESSAGE) + @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE) public Object instMessage; /** error name property */ @@ -62,6 +62,7 @@ return $nasgenmap$; } + @SuppressWarnings("LeakingThisInConstructor") private NativeEvalError(final Object msg, final ScriptObject proto, final PropertyMap map) { super(proto, map); if (msg != UNDEFINED) { @@ -69,6 +70,7 @@ } else { this.delete(NativeError.MESSAGE, false); } + NativeError.initException(this); } NativeEvalError(final Object msg, final Global global) { diff -r 9d430eab0c44 -r f73a809e4b06 nashorn/src/jdk/nashorn/internal/objects/NativeRangeError.java --- a/nashorn/src/jdk/nashorn/internal/objects/NativeRangeError.java Wed Jan 15 10:24:42 2014 -0800 +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeRangeError.java Thu Jan 16 21:46:17 2014 -0800 @@ -44,7 +44,7 @@ public final class NativeRangeError extends ScriptObject { /** message property in instance */ - @Property(name = NativeError.MESSAGE) + @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE) public Object instMessage; /** error name property */ @@ -62,6 +62,7 @@ return $nasgenmap$; } + @SuppressWarnings("LeakingThisInConstructor") private NativeRangeError(final Object msg, final ScriptObject proto, final PropertyMap map) { super(proto, map); if (msg != UNDEFINED) { @@ -69,6 +70,7 @@ } else { this.delete(NativeError.MESSAGE, false); } + NativeError.initException(this); } NativeRangeError(final Object msg, final Global global) { diff -r 9d430eab0c44 -r f73a809e4b06 nashorn/src/jdk/nashorn/internal/objects/NativeReferenceError.java --- a/nashorn/src/jdk/nashorn/internal/objects/NativeReferenceError.java Wed Jan 15 10:24:42 2014 -0800 +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeReferenceError.java Thu Jan 16 21:46:17 2014 -0800 @@ -44,7 +44,7 @@ public final class NativeReferenceError extends ScriptObject { /** message property in instance */ - @Property(name = NativeError.MESSAGE) + @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE) public Object instMessage; /** error name property */ @@ -62,6 +62,7 @@ return $nasgenmap$; } + @SuppressWarnings("LeakingThisInConstructor") private NativeReferenceError(final Object msg, final ScriptObject proto, final PropertyMap map) { super(proto, map); if (msg != UNDEFINED) { @@ -69,6 +70,7 @@ } else { this.delete(NativeError.MESSAGE, false); } + NativeError.initException(this); } NativeReferenceError(final Object msg, final Global global) { diff -r 9d430eab0c44 -r f73a809e4b06 nashorn/src/jdk/nashorn/internal/objects/NativeSyntaxError.java --- a/nashorn/src/jdk/nashorn/internal/objects/NativeSyntaxError.java Wed Jan 15 10:24:42 2014 -0800 +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeSyntaxError.java Thu Jan 16 21:46:17 2014 -0800 @@ -44,7 +44,7 @@ public final class NativeSyntaxError extends ScriptObject { /** message property in instance */ - @Property(name = NativeError.MESSAGE) + @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE) public Object instMessage; /** error name property */ @@ -62,6 +62,7 @@ return $nasgenmap$; } + @SuppressWarnings("LeakingThisInConstructor") NativeSyntaxError(final Object msg, final Global global) { super(global.getSyntaxErrorPrototype(), global.getSyntaxErrorMap()); if (msg != UNDEFINED) { @@ -69,6 +70,7 @@ } else { this.delete(NativeError.MESSAGE, false); } + NativeError.initException(this); } private NativeSyntaxError(final Object msg) { diff -r 9d430eab0c44 -r f73a809e4b06 nashorn/src/jdk/nashorn/internal/objects/NativeTypeError.java --- a/nashorn/src/jdk/nashorn/internal/objects/NativeTypeError.java Wed Jan 15 10:24:42 2014 -0800 +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeTypeError.java Thu Jan 16 21:46:17 2014 -0800 @@ -44,7 +44,7 @@ public final class NativeTypeError extends ScriptObject { /** message property in instance */ - @Property(name = NativeError.MESSAGE) + @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE) public Object instMessage; /** error name property */ @@ -62,6 +62,7 @@ return $nasgenmap$; } + @SuppressWarnings("LeakingThisInConstructor") NativeTypeError(final Object msg, final Global global) { super(global.getTypeErrorPrototype(), global.getTypeErrorMap()); if (msg != UNDEFINED) { @@ -69,6 +70,7 @@ } else { delete(NativeError.MESSAGE, false); } + NativeError.initException(this); } private NativeTypeError(final Object msg) { diff -r 9d430eab0c44 -r f73a809e4b06 nashorn/src/jdk/nashorn/internal/objects/NativeURIError.java --- a/nashorn/src/jdk/nashorn/internal/objects/NativeURIError.java Wed Jan 15 10:24:42 2014 -0800 +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeURIError.java Thu Jan 16 21:46:17 2014 -0800 @@ -43,7 +43,7 @@ public final class NativeURIError extends ScriptObject { /** message property in instance */ - @Property(name = NativeError.MESSAGE) + @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE) public Object instMessage; /** error name property */ @@ -61,6 +61,7 @@ return $nasgenmap$; } + @SuppressWarnings("LeakingThisInConstructor") NativeURIError(final Object msg, final Global global) { super(global.getURIErrorPrototype(), global.getURIErrorMap()); if (msg != UNDEFINED) { @@ -68,6 +69,7 @@ } else { this.delete(NativeError.MESSAGE, false); } + NativeError.initException(this); } private NativeURIError(final Object msg) { diff -r 9d430eab0c44 -r f73a809e4b06 nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java --- a/nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java Wed Jan 15 10:24:42 2014 -0800 +++ b/nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java Thu Jan 16 21:46:17 2014 -0800 @@ -25,7 +25,7 @@ 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; @@ -33,6 +33,7 @@ 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 @@ -44,9 +45,9 @@ @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); @@ -57,23 +58,21 @@ 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 @@ -85,6 +84,35 @@ } /** + * 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 */ @@ -257,6 +285,8 @@ 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); } } } diff -r 9d430eab0c44 -r f73a809e4b06 nashorn/test/script/basic/JDK-8031983.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8031983.js Thu Jan 16 21:46:17 2014 -0800 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, 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-8031983: Error objects should capture stack at the constructor + * + * @test + * @run + */ + +var e = new Error(); +print("hello"); + +try { + throw e; +} catch (e) { + print(e.lineNumber); + print(e.stack.replace(/\\/g, '/')); +} + +Error.captureStackTrace(e); +try { + throw e; +} catch (e) { + print(e.lineNumber); + print(e.stack.replace(/\\/g, '/')); +} + +var obj = {}; +Error.captureStackTrace(obj); +try { + throw obj; +} catch (e) { + print(e.stack.replace(/\\/g, '/')); +} diff -r 9d430eab0c44 -r f73a809e4b06 nashorn/test/script/basic/JDK-8031983.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8031983.js.EXPECTED Thu Jan 16 21:46:17 2014 -0800 @@ -0,0 +1,9 @@ +hello +35 +Error + at (test/script/basic/JDK-8031983.js:31) +43 +Error + at (test/script/basic/JDK-8031983.js:41) +[object Object] + at (test/script/basic/JDK-8031983.js:50) diff -r 9d430eab0c44 -r f73a809e4b06 nashorn/test/script/basic/JDK-8032004.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8032004.js Thu Jan 16 21:46:17 2014 -0800 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, 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-8032004: instance property "message" of Error objects should be non-enumerable + * + * @test + * @run + */ + +function check(obj) { + if (obj.propertyIsEnumerable("message")) { + fail(obj.name + " object's message property is enumerable!"); + } +} + +check(new Error("test")); +check(new EvalError("test")); +check(new RangeError("test")); +check(new ReferenceError("test")); +check(new SyntaxError("test")); +check(new TypeError("test")); +check(new URIError("test")); diff -r 9d430eab0c44 -r f73a809e4b06 nashorn/test/script/basic/NASHORN-111.js.EXPECTED --- a/nashorn/test/script/basic/NASHORN-111.js.EXPECTED Wed Jan 15 10:24:42 2014 -0800 +++ b/nashorn/test/script/basic/NASHORN-111.js.EXPECTED Thu Jan 16 21:46:17 2014 -0800 @@ -1,1 +1,1 @@ -{"message":"type error"} +{} diff -r 9d430eab0c44 -r f73a809e4b06 nashorn/test/script/basic/NASHORN-441.js.EXPECTED --- a/nashorn/test/script/basic/NASHORN-441.js.EXPECTED Wed Jan 15 10:24:42 2014 -0800 +++ b/nashorn/test/script/basic/NASHORN-441.js.EXPECTED Thu Jan 16 21:46:17 2014 -0800 @@ -12,6 +12,6 @@ try 5 rethrow 5 finally 5 -Error: try 5 thrown in line 71 +Error: try 5 thrown in line 74 try 6 finally 6