# HG changeset patch # User sundar # Date 1385988566 -19800 # Node ID c150d042ffff6e8f959790b1a63bd8dae87e8e59 # Parent 4771a8ce90376f367e7d10d06db111e12fa48b75 8029364: NashornException to expose thrown object Reviewed-by: lagergren, jlaskey diff -r 4771a8ce9037 -r c150d042ffff nashorn/src/jdk/nashorn/api/scripting/NashornException.java --- a/nashorn/src/jdk/nashorn/api/scripting/NashornException.java Wed Nov 27 14:13:52 2013 +0530 +++ b/nashorn/src/jdk/nashorn/api/scripting/NashornException.java Mon Dec 02 18:19:26 2013 +0530 @@ -29,6 +29,7 @@ import java.util.List; import jdk.nashorn.internal.codegen.CompilerConstants; import jdk.nashorn.internal.runtime.ECMAErrors; +import jdk.nashorn.internal.runtime.ScriptObject; /** * This is base exception for all Nashorn exceptions. These originate from @@ -49,6 +50,8 @@ private final int line; // script column number private final int column; + // underlying ECMA error object - lazily initialized + private Object ecmaError; /** script source name used for "engine.js" */ public static final String ENGINE_SCRIPT_SOURCE_NAME = "nashorn:engine/resources/engine.js"; @@ -188,4 +191,33 @@ } return buf.toString(); } + + protected Object getThrown() { + return null; + } + + protected NashornException initEcmaError(final ScriptObject global) { + if (ecmaError != null) { + return this; // initialized already! + } + + final Object thrown = getThrown(); + if (thrown instanceof ScriptObject) { + ecmaError = ScriptObjectMirror.wrap(thrown, global); + } else { + ecmaError = thrown; + } + + return this; + } + + /** + * Return the underlying ECMA error object, if available. + * + * @return underlying ECMA Error object's mirror or whatever was thrown + * from script such as a String, Number or a Boolean. + */ + public Object getEcmaError() { + return ecmaError; + } } diff -r 4771a8ce9037 -r c150d042ffff nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java --- a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Wed Nov 27 14:13:52 2013 +0530 +++ b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Mon Dec 02 18:19:26 2013 +0530 @@ -476,16 +476,19 @@ private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException { name.getClass(); // null check + ScriptObject invokeGlobal = null; ScriptObjectMirror selfMirror = null; if (selfObject instanceof ScriptObjectMirror) { selfMirror = (ScriptObjectMirror)selfObject; if (! isOfContext(selfMirror.getHomeGlobal(), nashornContext)) { throw new IllegalArgumentException(getMessage("script.object.from.another.engine")); } + invokeGlobal = selfMirror.getHomeGlobal(); } else if (selfObject instanceof ScriptObject) { // invokeMethod called from script code - in which case we may get 'naked' ScriptObject // Wrap it with oldGlobal to make a ScriptObjectMirror for the same. final ScriptObject oldGlobal = Context.getGlobal(); + invokeGlobal = oldGlobal; if (oldGlobal == null) { throw new IllegalArgumentException(getMessage("no.current.nashorn.global")); } @@ -498,6 +501,7 @@ } else if (selfObject == null) { // selfObject is null => global function call final ScriptObject ctxtGlobal = getNashornGlobalFrom(context); + invokeGlobal = ctxtGlobal; selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(ctxtGlobal, ctxtGlobal); } @@ -509,7 +513,7 @@ if (cause instanceof NoSuchMethodException) { throw (NoSuchMethodException)cause; } - throwAsScriptException(e); + throwAsScriptException(e, invokeGlobal); throw new AssertionError("should not reach here"); } } @@ -543,7 +547,7 @@ } return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal)); } catch (final Exception e) { - throwAsScriptException(e); + throwAsScriptException(e, ctxtGlobal); throw new AssertionError("should not reach here"); } finally { if (globalChanged) { @@ -552,7 +556,7 @@ } } - private static void throwAsScriptException(final Exception e) throws ScriptException { + private static void throwAsScriptException(final Exception e, final ScriptObject global) throws ScriptException { if (e instanceof ScriptException) { throw (ScriptException)e; } else if (e instanceof NashornException) { @@ -560,6 +564,7 @@ final ScriptException se = new ScriptException( ne.getMessage(), ne.getFileName(), ne.getLineNumber(), ne.getColumnNumber()); + ne.initEcmaError(global); se.initCause(e); throw se; } else if (e instanceof RuntimeException) { @@ -605,7 +610,7 @@ return nashornContext.compileScript(source, newGlobal); } catch (final Exception e) { - throwAsScriptException(e); + throwAsScriptException(e, newGlobal); throw new AssertionError("should not reach here"); } finally { if (globalChanged) { diff -r 4771a8ce9037 -r c150d042ffff nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java --- a/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Wed Nov 27 14:13:52 2013 +0530 +++ b/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Mon Dec 02 18:19:26 2013 +0530 @@ -108,6 +108,8 @@ } throw new RuntimeException("not a function: " + toString()); + } catch (final NashornException ne) { + throw ne.initEcmaError(global); } catch (final RuntimeException | Error e) { throw e; } catch (final Throwable t) { @@ -135,6 +137,8 @@ } throw new RuntimeException("not a constructor: " + toString()); + } catch (final NashornException ne) { + throw ne.initEcmaError(global); } catch (final RuntimeException | Error e) { throw e; } catch (final Throwable t) { @@ -182,6 +186,8 @@ } throw new NoSuchMethodException("No such function " + functionName); + } catch (final NashornException ne) { + throw ne.initEcmaError(global); } catch (final RuntimeException | Error e) { throw e; } catch (final Throwable t) { @@ -717,6 +723,8 @@ } try { return callable.call(); + } catch (final NashornException ne) { + throw ne.initEcmaError(global); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { diff -r 4771a8ce9037 -r c150d042ffff nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java --- a/nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java Wed Nov 27 14:13:52 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java Mon Dec 02 18:19:26 2013 +0530 @@ -88,6 +88,7 @@ * Get the thrown object * @return thrown object */ + @Override public Object getThrown() { return thrown; } diff -r 4771a8ce9037 -r c150d042ffff nashorn/test/script/basic/JDK-8029364.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8029364.js Mon Dec 02 18:19:26 2013 +0530 @@ -0,0 +1,49 @@ +/* + * 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-8029364: NashornException to expose thrown object + * + * @test + * @run + */ + +var m = new javax.script.ScriptEngineManager(); +var e = m.getEngineByName("nashorn"); +var g = e.eval("this"); +try { + e.eval("var e = new Error('foo'); e.bar = 33; throw e"); +} catch (se) { + // ScriptException instance's cause is a NashornException + print(se.getClass()); + var cause = se.cause; + print(cause.getClass()); + // NashornException instance has 'ecmaError' bean getter + print(cause.ecmaError); + // access to underlying ECMA Error object + print(cause.ecmaError instanceof g.Error); + print(cause.ecmaError.name); + print(cause.ecmaError.message); + print(cause.ecmaError.bar); +} + diff -r 4771a8ce9037 -r c150d042ffff nashorn/test/script/basic/JDK-8029364.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8029364.js.EXPECTED Mon Dec 02 18:19:26 2013 +0530 @@ -0,0 +1,7 @@ +class javax.script.ScriptException +class jdk.nashorn.internal.runtime.ECMAException +Error: foo +true +Error +foo +33