Coerce values obtained from polyglot calls (#5832)

Coerce values obtained from polyglot calls to fix #5177.

# Important Notes
Adds `IntHolder` class into the `test/Tests` project to simulate access to a class with integer field.
This commit is contained in:
Jaroslav Tulach 2023-03-07 19:21:30 +01:00 committed by GitHub
parent 1687dccda4
commit e3f0888c5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 4 deletions

View File

@ -7,6 +7,7 @@ import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.profiles.BranchProfile;
import org.enso.interpreter.Constants;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode;
import org.enso.interpreter.node.expression.builtin.text.util.ExpectStringNode;
import org.enso.interpreter.runtime.error.PanicException;
@ -16,6 +17,7 @@ import org.enso.interpreter.runtime.error.PanicException;
description = "Gets a member by name from a polyglot object.",
autoRegister = false)
public class GetMemberNode extends Node {
private @Child HostValueToEnsoNode fromHost = HostValueToEnsoNode.build();
private @Child InteropLibrary library =
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
private @Child ExpectStringNode expectStringNode = ExpectStringNode.build();
@ -23,7 +25,8 @@ public class GetMemberNode extends Node {
Object execute(Object object, Object member_name) {
try {
return library.readMember(object, expectStringNode.execute(member_name));
var value = library.readMember(object, expectStringNode.execute(member_name));
return fromHost.execute(value);
} catch (UnsupportedMessageException | UnknownIdentifierException e) {
err.enter();
throw new PanicException(e.getMessage(), this);

View File

@ -10,6 +10,7 @@ import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.profiles.BranchProfile;
import org.enso.interpreter.Constants;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode;
import org.enso.interpreter.node.expression.builtin.mutable.CoerceArrayNode;
import org.enso.interpreter.runtime.error.PanicException;
@ -19,7 +20,7 @@ import org.enso.interpreter.runtime.error.PanicException;
description = "Instantiates a polyglot constructor.",
autoRegister = false)
public abstract class InstantiateNode extends Node {
@Child private HostValueToEnsoNode fromHost = HostValueToEnsoNode.build();
private @Child InteropLibrary library =
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
private final BranchProfile err = BranchProfile.create();
@ -34,7 +35,8 @@ public abstract class InstantiateNode extends Node {
Object doExecute(
Object constructor, Object arguments, @Cached("build()") CoerceArrayNode coerce) {
try {
return library.instantiate(constructor, coerce.execute(arguments));
var value = library.instantiate(constructor, coerce.execute(arguments));
return fromHost.execute(value);
} catch (UnsupportedMessageException | ArityException | UnsupportedTypeException e) {
err.enter();
throw new PanicException(e.getMessage(), this);

View File

@ -0,0 +1,11 @@
package org.enso.base_test_helpers;
public final class IntHolder {
public final int value;
public final Integer boxed;
public IntHolder(int value) {
this.value = value;
this.boxed = value;
}
}

View File

@ -3,9 +3,12 @@ from Standard.Base import all
from Standard.Test import Test, Test_Suite
import Standard.Test.Extensions
polyglot java import java.time.LocalDate
polyglot java import java.lang.Double
polyglot java import java.lang.Integer
polyglot java import java.lang.String
polyglot java import java.time.LocalDate
polyglot java import java.util.function.Function
polyglot java import org.enso.base_test_helpers.IntHolder
spec = Test.group "Polyglot" <|
Test.specify "should be able to invoke a polyglot method by name and pass arguments" <|
@ -19,9 +22,32 @@ spec = Test.group "Polyglot" <|
Polyglot.new String ["42"] . should_equal "42"
Polyglot.new String ["42"].to_array . should_equal "42"
Test.specify "use Integer created by constructor" <|
Polyglot.new Integer [42] . should_equal 42
Test.specify "use Double created by constructor" <|
Polyglot.new Double [42] . should_equal 42
Test.specify "use Integer read from Polyglot object" <|
(Polyglot.get_member js_meaning "meaning") . should_equal 42
Test.specify "access Integer field from Polyglot object" <|
js_meaning.meaning . should_equal 42
Test.specify "use Integer obtained from a call" <|
Integer.parseInt "42" . should_equal 42
Test.specify "use Integer obtained from a read" <|
hold = IntHolder.new (6 * 7)
hold.value . should_equal 42
hold.boxed . should_equal 42
Test.specify "should be able to execute a polyglot function object along with corresponding arguments" <|
fun = Function.identity
Polyglot.execute fun ["42"] . should_equal "42"
Polyglot.execute fun ["42"].to_array . should_equal "42"
foreign js js_meaning = """
return { meaning : 6 * 7 };
main = Test_Suite.run_main spec