From 4f17f83d2f0fca496d82b2b517f45f5b032c7ef3 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Mon, 26 Jul 2021 14:12:59 +0200 Subject: [PATCH] [GR-32787] PolyglotException should use interop messages to obtain exception message. --- .../test/polyglot/PolyglotExceptionTest.java | 46 ++++++++++++++++++- .../polyglot/PolyglotExceptionImpl.java | 41 ++++++++--------- 2 files changed, 64 insertions(+), 23 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/PolyglotExceptionTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/PolyglotExceptionTest.java index 09e4f5679278..825e8b58a7b2 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/PolyglotExceptionTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/PolyglotExceptionTest.java @@ -94,12 +94,29 @@ public class PolyglotExceptionTest extends AbstractPolyglotTest { + @ExportLibrary(InteropLibrary.class) @SuppressWarnings("serial") - private static class TestGuestError extends AbstractTruffleException { + static class TestGuestError extends AbstractTruffleException { + + String exceptionMessage; TestGuestError() { super("MyError"); } + + @ExportMessage + boolean hasExceptionMessage() { + return exceptionMessage != null; + } + + @ExportMessage + Object getExceptionMessage() throws UnsupportedMessageException { + if (exceptionMessage != null) { + return exceptionMessage; + } else { + throw UnsupportedMessageException.create(); + } + } } @Test @@ -587,6 +604,33 @@ public String getName() { executorService.awaitTermination(100, TimeUnit.SECONDS); } + @Test + public void testExceptionMessage() { + try (Context ctx = Context.create()) { + TestGuestError guestError = new TestGuestError(); + guestError.exceptionMessage = "interop exception message"; + CauseErrorTruffleObject causeError = new CauseErrorTruffleObject(); + causeError.thrownError = guestError; + Value throwError = ctx.asValue(causeError); + try { + throwError.execute(); + Assert.fail(); + } catch (PolyglotException e) { + Assert.assertEquals("interop exception message", e.getMessage()); + Assert.assertTrue(e.isGuestException()); + } + + guestError.exceptionMessage = null; + try { + throwError.execute(); + Assert.fail(); + } catch (PolyglotException e) { + Assert.assertEquals("MyError", e.getMessage()); + Assert.assertTrue(e.isGuestException()); + } + } + } + abstract static class BaseNode extends Node { abstract Object execute(VirtualFrame frame); } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionImpl.java index 3e03dda17120..543a4d6212a7 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionImpl.java @@ -123,6 +123,7 @@ final class PolyglotExceptionImpl { this.guestFrames = TruffleStackTrace.getStackTrace(original); this.showInternalStackFrames = engine == null ? false : engine.engineOptionValues.get(PolyglotEngineOptions.ShowInternalStackFrames); Error resourceLimitError = getResourceLimitError(engine, exception); + String exceptionMessage = null; InteropLibrary interop; if (allowInterop && (interop = InteropLibrary.getUncached()).isException(exception)) { try { @@ -138,7 +139,9 @@ final class PolyglotExceptionImpl { this.exitStatus = this.exit ? interop.getExceptionExitStatus(exception) : 0; this.incompleteSource = this.syntaxError ? interop.isExceptionIncompleteSource(exception) : false; this.interrupted = (exceptionType == ExceptionType.INTERRUPT) && !this.cancelled; - + if (interop.hasExceptionMessage(exception)) { + exceptionMessage = interop.asString(interop.getExceptionMessage(exception)); + } if (interop.hasSourceLocation(exception)) { this.sourceLocation = newSourceSection(interop.getSourceLocation(exception)); } else { @@ -204,28 +207,22 @@ final class PolyglotExceptionImpl { } this.sourceLocation = location != null ? newSourceSection(location) : null; } - if (isHostException()) { - this.message = asHostException().getMessage(); - } else { - if (internal) { - this.message = exception.toString(); - } else { - String exceptionMessage = exception.getMessage(); - if (exceptionMessage != null) { - this.message = exceptionMessage; - } else if (resourceLimitError != null) { - String resourceExhaustedMessage = "Resource exhausted"; - if (resourceLimitError instanceof StackOverflowError) { - resourceExhaustedMessage += ": Stack overflow"; - } - if (resourceLimitError instanceof OutOfMemoryError) { - resourceExhaustedMessage += ": Out of memory"; - } - this.message = resourceExhaustedMessage; - } else { - this.message = null; - } + if (exceptionMessage == null) { + exceptionMessage = isHostException() ? asHostException().getMessage() : internal ? exception.toString() : exception.getMessage(); + } + if (exceptionMessage != null) { + this.message = exceptionMessage; + } else if (resourceLimitError != null) { + String resourceExhaustedMessage = "Resource exhausted"; + if (resourceLimitError instanceof StackOverflowError) { + resourceExhaustedMessage += ": Stack overflow"; } + if (resourceLimitError instanceof OutOfMemoryError) { + resourceExhaustedMessage += ": Out of memory"; + } + this.message = resourceExhaustedMessage; + } else { + this.message = null; } // late materialization of host frames. only needed if polyglot exceptions cross the