Skip to content

Commit ad01302

Browse files
committed
[GR-54865] Make sure custom type converters take precedence over internal collection mappings.
PullRequest: graal/19725
2 parents cdada02 + 55a282d commit ad01302

File tree

3 files changed

+175
-15
lines changed

3 files changed

+175
-15
lines changed

espresso/src/com.oracle.truffle.espresso.polyglot/src/com/oracle/truffle/espresso/polyglot/GuestTypeConversion.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2024, 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
@@ -40,6 +40,23 @@
4040
*/
4141
package com.oracle.truffle.espresso.polyglot;
4242

43+
/**
44+
* This interface must be implemented by a custom defined type converter that is declared as context
45+
* builder input using the 'java.PolyglotTypeConverters' option. If a polyglot object that is passed
46+
* into Espresso has a declared meta name that matches the declaration used for the GuestConversion,
47+
* the toGuest method is invoked. This invocation is responsible for returning a guest object
48+
* matching the parameterized type.
49+
* </p>
50+
* Note that, in the case where the target type, e.g. a method parameter type in the guest, is not
51+
* assignable from the returned instance of the toGuest method, the converted value is ignored.
52+
* Hence, other custom or internal type mappings might be attempted in sequence in response to such
53+
* incompatible conversion. For example, the built-in collection type mappings
54+
* (java.BuiltInPolyglotCollections) might be compatible for the incoming polyglot object, or there
55+
* might be custom interface mapping (java.PolyglotInterfaceMappings).
56+
*
57+
* @param <T> the guest type this converter is converting an interop meta name-mapped polyglot
58+
* instance to.
59+
*/
4360
public interface GuestTypeConversion<T> {
4461
T toGuest(Object polyglotInstance);
4562
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/ToEspressoNode.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ public static Object doArray(Object value, ArrayKlass targetType,
241241
public static Object doTypeConverter(Object value, EspressoType targetType,
242242
@Bind Node node,
243243
@Cached LookupTypeConverterNode lookupTypeConverter,
244+
@Cached InstanceOf.Dynamic instanceOf,
244245
@CachedLibrary(limit = "LIMIT") InteropLibrary interop,
245246
@Cached InlinedBranchProfile error) throws UnsupportedTypeException {
246247
try {
@@ -254,7 +255,10 @@ public static Object doTypeConverter(Object value, EspressoType targetType,
254255
if (targetType instanceof ParameterizedEspressoType parameterizedEspressoType) {
255256
EspressoLanguage.get(node).getTypeArgumentProperty().setObject(foreignWrapper, parameterizedEspressoType.getTypeArguments());
256257
}
257-
return converter.convert(foreignWrapper);
258+
StaticObject result = (StaticObject) converter.convert(foreignWrapper);
259+
if (instanceOf.execute(result.getKlass(), targetType.getRawType())) {
260+
return result;
261+
}
258262
}
259263
} catch (UnsupportedMessageException e) {
260264
// no meta object, fall through to throw unsupported type
@@ -297,13 +301,28 @@ public static Object doInternalTypeConverter(Object value, EspressoType targetTy
297301
})
298302
public static Object doBuiltinCollectionMapped(Object value, EspressoType targetType,
299303
@Bind Node node,
304+
@Cached LookupTypeConverterNode lookupTypeConverterNode,
300305
@Cached LookupProxyKlassNode lookupProxyKlassNode,
301306
@Cached ProxyInstantiateNode proxyInstantiateNode,
307+
@Cached InstanceOf.Dynamic instanceOf,
302308
@CachedLibrary(limit = "LIMIT") InteropLibrary interop,
309+
@Cached InlinedBranchProfile converterProfile,
303310
@Cached InlinedBranchProfile errorProfile) throws UnsupportedTypeException {
304311
try {
305312
Object metaObject = interop.getMetaObject(value);
306313
String metaName = getMetaName(metaObject, interop);
314+
// first check if there's a user-defined custom type converter defined
315+
PolyglotTypeMappings.TypeConverter converter = lookupTypeConverterNode.execute(metaName);
316+
if (converter != null) {
317+
converterProfile.enter(node);
318+
EspressoContext context = EspressoContext.get(node);
319+
StaticObject foreignWrapper = StaticObject.createForeign(context.getLanguage(), context.getMeta().java_lang_Object, value, interop);
320+
StaticObject result = (StaticObject) converter.convert(foreignWrapper);
321+
if (instanceOf.execute(result.getKlass(), targetType.getRawType())) {
322+
return result;
323+
}
324+
}
325+
// then check if there's a type-mapped interface
307326
WrappedProxyKlass proxyKlass = lookupProxyKlassNode.execute(metaObject, metaName, targetType.getRawType());
308327
if (proxyKlass != null) {
309328
return proxyInstantiateNode.execute(proxyKlass, value, targetType);

0 commit comments

Comments
 (0)