Skip to content

Commit b2291ca

Browse files
committed
[GR-44969] Avoid using toDisplayString for host exception ToString conversion.
PullRequest: js/2753
2 parents 3cd9f31 + 76e4135 commit b2291ca

File tree

4 files changed

+57
-19
lines changed

4 files changed

+57
-19
lines changed

graal-js/src/com.oracle.truffle.js.test/js/interop/foreign_error_prototype.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ try {
3838
assertSame(message, e.message);
3939
assertTrue(e.stack.includes('foreign_error_prototype'));
4040
assertTrue(e.stack.includes('throwJavaError'));
41-
assertSame('Error: ' + message, Error.prototype.toString.call(e));
41+
assertSame('java.lang.RuntimeException: ' + message, Error.prototype.toString.call(e));
4242

4343
assertSame(undefined, e.cause);
4444
}
@@ -55,7 +55,7 @@ try {
5555
assertSame(otherMessage, e.message);
5656
assertTrue(e.stack.includes('foreign_error_prototype'));
5757
assertTrue(e.stack.includes('throwJavaErrorWithCause'));
58-
assertSame('Error: ' + otherMessage, Error.prototype.toString.call(e));
58+
assertSame('java.lang.RuntimeException: ' + otherMessage, Error.prototype.toString.call(e));
5959

6060
assertSame(cause, e.cause);
6161

@@ -64,7 +64,7 @@ try {
6464
assertSame(message, e.message);
6565
assertTrue(e.stack.includes('foreign_error_prototype'));
6666
assertTrue(e.stack.includes('throwJavaError'));
67-
assertSame('Error: ' + message, Error.prototype.toString.call(e));
67+
assertSame('java.lang.RuntimeException: ' + message, Error.prototype.toString.call(e));
6868

6969
assertSame(undefined, e.cause);
7070
}
@@ -96,7 +96,7 @@ try {
9696
assertSame(message, e.message);
9797
assertTrue(e.stack.includes('foreign_error_prototype'));
9898
assertTrue(e.stack.includes('throwJavaError'));
99-
assertSame('Error: ' + message, Error.prototype.toString.call(e));
99+
assertSame('java.lang.RuntimeException: ' + message, Error.prototype.toString.call(e));
100100

101101
assertSame(undefined, e.cause);
102102
}
@@ -115,7 +115,10 @@ try {
115115
assertTrue(e.stack.includes('foreign_error_prototype'));
116116
assertTrue(e.stack.includes('throwJavaErrorFromJava'));
117117
assertTrue(e.stack.includes('java.util.Objects.requireNonNull'));
118-
assertSame('Error: ' + message, Error.prototype.toString.call(e));
118+
assertSame('java.lang.NullPointerException: ' + message, Error.prototype.toString.call(e));
119119

120120
assertSame(undefined, e.cause);
121121
}
122+
123+
assertSame('java.lang.RuntimeException', String(new java.lang.RuntimeException()));
124+
assertSame('java.lang.RuntimeException: ' + message, String(new java.lang.RuntimeException(message)));

graal-js/src/com.oracle.truffle.js.test/src/com/oracle/truffle/js/test/interop/JavaScriptHostInteropTest.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -293,6 +293,23 @@ public void explicitMethodOverloadTest() {
293293
}
294294
}
295295

296+
@Test
297+
public void hostExceptionToString() {
298+
// No host access to Throwable.toString().
299+
try (Context context = JSTest.newContextBuilder().allowHostAccess(HostAccess.EXPLICIT).build()) {
300+
Value toString = context.eval(ID, "String");
301+
302+
String message = "someMessage";
303+
var exceptionWithoutMessage = new RuntimeException();
304+
var exceptionWithMessage = new RuntimeException(message);
305+
306+
assertFalse(context.asValue(exceptionWithMessage).hasMember("toString"));
307+
assertFalse(context.asValue(exceptionWithMessage).hasMember("toString"));
308+
assertEquals(exceptionWithoutMessage.getClass().getName(), toString.execute(exceptionWithoutMessage).asString());
309+
assertEquals(exceptionWithMessage.getClass().getName() + ": " + message, toString.execute(exceptionWithMessage).asString());
310+
}
311+
}
312+
296313
public static class ExceptionVerifier implements Consumer<PolyglotException> {
297314
private final String[] substrings;
298315

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/builtins/ErrorPrototypeBuiltins.java

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import com.oracle.truffle.js.builtins.ErrorPrototypeBuiltinsFactory.ErrorPrototypeToStringNodeGen;
5555
import com.oracle.truffle.js.builtins.ErrorPrototypeBuiltinsFactory.ForeignErrorPrototypeCauseNodeGen;
5656
import com.oracle.truffle.js.builtins.ErrorPrototypeBuiltinsFactory.ForeignErrorPrototypeMessageNodeGen;
57+
import com.oracle.truffle.js.builtins.ErrorPrototypeBuiltinsFactory.ForeignErrorPrototypeNameNodeGen;
5758
import com.oracle.truffle.js.builtins.ErrorPrototypeBuiltinsFactory.ForeignErrorPrototypeStackNodeGen;
5859
import com.oracle.truffle.js.nodes.access.IsObjectNode;
5960
import com.oracle.truffle.js.nodes.access.PropertyGetNode;
@@ -157,11 +158,11 @@ protected Object toStringObject(Object errorObj,
157158
if (Strings.length(strMessage) == 0) {
158159
return strName;
159160
}
160-
return toStringIntl(strName, strMessage);
161+
return concatNameAndMessage(strName, strMessage);
161162
}
162163

163164
@TruffleBoundary
164-
private static Object toStringIntl(TruffleString strName, TruffleString strMessage) {
165+
private static Object concatNameAndMessage(TruffleString strName, TruffleString strMessage) {
165166
return Strings.concatAll(strName, Strings.COLON_SPACE, strMessage);
166167
}
167168

@@ -207,6 +208,7 @@ protected ForeignErrorPrototypeBuiltins() {
207208
public enum ForeignError implements BuiltinEnum<ForeignError> {
208209
cause(0),
209210
message(0),
211+
name(0),
210212
stack(0);
211213

212214
private final int length;
@@ -233,6 +235,8 @@ protected Object createNode(JSContext context, JSBuiltin builtin, boolean constr
233235
return ForeignErrorPrototypeCauseNodeGen.create(context, builtin, args().withThis().createArgumentNodes(context));
234236
case message:
235237
return ForeignErrorPrototypeMessageNodeGen.create(context, builtin, args().withThis().createArgumentNodes(context));
238+
case name:
239+
return ForeignErrorPrototypeNameNodeGen.create(context, builtin, args().withThis().createArgumentNodes(context));
236240
case stack:
237241
return ForeignErrorPrototypeStackNodeGen.create(context, builtin, args().withThis().createArgumentNodes(context));
238242
}
@@ -266,6 +270,31 @@ protected Object getMessage(Object error,
266270

267271
}
268272

273+
@ImportStatic(JSConfig.class)
274+
public abstract static class ForeignErrorPrototypeNameNode extends JSBuiltinNode {
275+
276+
public ForeignErrorPrototypeNameNode(JSContext context, JSBuiltin builtin) {
277+
super(context, builtin);
278+
}
279+
280+
@Specialization(limit = "InteropLibraryLimit")
281+
protected Object getName(Object error,
282+
@CachedLibrary("error") InteropLibrary interop,
283+
@CachedLibrary(limit = "InteropLibraryLimit") InteropLibrary interopMeta,
284+
@Cached ImportValueNode importNode) {
285+
try {
286+
if (interop.isException(error) && interop.hasMetaObject(error)) {
287+
return importNode.executeWithTarget(interopMeta.getMetaQualifiedName(interop.getMetaObject(error)));
288+
}
289+
} catch (UnsupportedMessageException e) {
290+
// Interop contract violation
291+
assert false : e;
292+
}
293+
return Strings.UC_ERROR;
294+
}
295+
296+
}
297+
269298
@ImportStatic(JSConfig.class)
270299
public abstract static class ForeignErrorPrototypeStackNode extends JSBuiltinNode {
271300

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/nodes/cast/JSToPrimitiveNode.java

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,6 @@ public static Object tryHostObjectToPrimitive(Object object, Hint hint, InteropL
258258
}
259259
} else if (interop.isMetaObject(object)) {
260260
return javaClassToString(object, interop);
261-
} else if (interop.isException(object)) {
262-
return javaExceptionToString(object, interop);
263261
}
264262
return null;
265263
}
@@ -278,15 +276,6 @@ private static TruffleString javaClassToString(Object object, InteropLibrary int
278276
}
279277
}
280278

281-
@TruffleBoundary
282-
private static TruffleString javaExceptionToString(Object object, InteropLibrary interop) {
283-
try {
284-
return InteropLibrary.getUncached().asTruffleString(interop.toDisplayString(object, true));
285-
} catch (UnsupportedMessageException e) {
286-
throw Errors.createTypeErrorInteropException(object, e, "toString", interop);
287-
}
288-
}
289-
290279
@Fallback
291280
protected TruffleString doFallback(Object value) {
292281
assert value != null;

0 commit comments

Comments
 (0)