Skip to content

Commit 4f17f83

Browse files
committed
[GR-32787] PolyglotException should use interop messages to obtain exception message.
1 parent 2de1b24 commit 4f17f83

File tree

2 files changed

+64
-23
lines changed

2 files changed

+64
-23
lines changed

truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/PolyglotExceptionTest.java

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,29 @@
9494

9595
public class PolyglotExceptionTest extends AbstractPolyglotTest {
9696

97+
@ExportLibrary(InteropLibrary.class)
9798
@SuppressWarnings("serial")
98-
private static class TestGuestError extends AbstractTruffleException {
99+
static class TestGuestError extends AbstractTruffleException {
100+
101+
String exceptionMessage;
99102

100103
TestGuestError() {
101104
super("MyError");
102105
}
106+
107+
@ExportMessage
108+
boolean hasExceptionMessage() {
109+
return exceptionMessage != null;
110+
}
111+
112+
@ExportMessage
113+
Object getExceptionMessage() throws UnsupportedMessageException {
114+
if (exceptionMessage != null) {
115+
return exceptionMessage;
116+
} else {
117+
throw UnsupportedMessageException.create();
118+
}
119+
}
103120
}
104121

105122
@Test
@@ -587,6 +604,33 @@ public String getName() {
587604
executorService.awaitTermination(100, TimeUnit.SECONDS);
588605
}
589606

607+
@Test
608+
public void testExceptionMessage() {
609+
try (Context ctx = Context.create()) {
610+
TestGuestError guestError = new TestGuestError();
611+
guestError.exceptionMessage = "interop exception message";
612+
CauseErrorTruffleObject causeError = new CauseErrorTruffleObject();
613+
causeError.thrownError = guestError;
614+
Value throwError = ctx.asValue(causeError);
615+
try {
616+
throwError.execute();
617+
Assert.fail();
618+
} catch (PolyglotException e) {
619+
Assert.assertEquals("interop exception message", e.getMessage());
620+
Assert.assertTrue(e.isGuestException());
621+
}
622+
623+
guestError.exceptionMessage = null;
624+
try {
625+
throwError.execute();
626+
Assert.fail();
627+
} catch (PolyglotException e) {
628+
Assert.assertEquals("MyError", e.getMessage());
629+
Assert.assertTrue(e.isGuestException());
630+
}
631+
}
632+
}
633+
590634
abstract static class BaseNode extends Node {
591635
abstract Object execute(VirtualFrame frame);
592636
}

truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionImpl.java

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ final class PolyglotExceptionImpl {
123123
this.guestFrames = TruffleStackTrace.getStackTrace(original);
124124
this.showInternalStackFrames = engine == null ? false : engine.engineOptionValues.get(PolyglotEngineOptions.ShowInternalStackFrames);
125125
Error resourceLimitError = getResourceLimitError(engine, exception);
126+
String exceptionMessage = null;
126127
InteropLibrary interop;
127128
if (allowInterop && (interop = InteropLibrary.getUncached()).isException(exception)) {
128129
try {
@@ -138,7 +139,9 @@ final class PolyglotExceptionImpl {
138139
this.exitStatus = this.exit ? interop.getExceptionExitStatus(exception) : 0;
139140
this.incompleteSource = this.syntaxError ? interop.isExceptionIncompleteSource(exception) : false;
140141
this.interrupted = (exceptionType == ExceptionType.INTERRUPT) && !this.cancelled;
141-
142+
if (interop.hasExceptionMessage(exception)) {
143+
exceptionMessage = interop.asString(interop.getExceptionMessage(exception));
144+
}
142145
if (interop.hasSourceLocation(exception)) {
143146
this.sourceLocation = newSourceSection(interop.getSourceLocation(exception));
144147
} else {
@@ -204,28 +207,22 @@ final class PolyglotExceptionImpl {
204207
}
205208
this.sourceLocation = location != null ? newSourceSection(location) : null;
206209
}
207-
if (isHostException()) {
208-
this.message = asHostException().getMessage();
209-
} else {
210-
if (internal) {
211-
this.message = exception.toString();
212-
} else {
213-
String exceptionMessage = exception.getMessage();
214-
if (exceptionMessage != null) {
215-
this.message = exceptionMessage;
216-
} else if (resourceLimitError != null) {
217-
String resourceExhaustedMessage = "Resource exhausted";
218-
if (resourceLimitError instanceof StackOverflowError) {
219-
resourceExhaustedMessage += ": Stack overflow";
220-
}
221-
if (resourceLimitError instanceof OutOfMemoryError) {
222-
resourceExhaustedMessage += ": Out of memory";
223-
}
224-
this.message = resourceExhaustedMessage;
225-
} else {
226-
this.message = null;
227-
}
210+
if (exceptionMessage == null) {
211+
exceptionMessage = isHostException() ? asHostException().getMessage() : internal ? exception.toString() : exception.getMessage();
212+
}
213+
if (exceptionMessage != null) {
214+
this.message = exceptionMessage;
215+
} else if (resourceLimitError != null) {
216+
String resourceExhaustedMessage = "Resource exhausted";
217+
if (resourceLimitError instanceof StackOverflowError) {
218+
resourceExhaustedMessage += ": Stack overflow";
228219
}
220+
if (resourceLimitError instanceof OutOfMemoryError) {
221+
resourceExhaustedMessage += ": Out of memory";
222+
}
223+
this.message = resourceExhaustedMessage;
224+
} else {
225+
this.message = null;
229226
}
230227

231228
// late materialization of host frames. only needed if polyglot exceptions cross the

0 commit comments

Comments
 (0)