polyglot --jvm --shell
GraalVM MultiLanguage Shell 19.0.0
Copyright (c) 2013-2019, Oracle and/or its affiliates
Python version 3.7.0
Ruby version 2.6.2
js> python>
python> from collections import deque
python> d = deque(maxlen=42)
python> import polyglot
python> polyglot.export_value(d, 'd')
deque([], maxlen=42)
python> js>
js> Polyglot.import('d').maxlen
42
js> ruby>
ruby> Polyglot.import('d')
<foreign>
ruby> Polyglot.import('d').maxlen
Internal error occured: org.graalvm.polyglot.PolyglotException: org.truffleruby.language.control.RaiseException: Message not supported. (UnsupportedMessageException)
from com.oracle.truffle.api.interop.UnsupportedMessageException.create(UnsupportedMessageException.java:118)
from com.oracle.graal.python.builtins.objects.PythonAbstractObject$PExecuteNode.doExecute(PythonAbstractObject.java:783)
from com.oracle.graal.python.builtins.objects.PythonAbstractObjectFactory$PExecuteNodeGen.executeAndSpecialize(PythonAbstractObjectFactory.java:549)
from com.oracle.graal.python.builtins.objects.PythonAbstractObjectFactory$PExecuteNodeGen.execute(PythonAbstractObjectFactory.java:531)
from com.oracle.graal.python.builtins.objects.PythonAbstractObject.invokeMember(PythonAbstractObject.java:427)
from com.oracle.graal.python.builtins.objects.PythonAbstractObjectGen$InteropLibraryExports$Cached.invokeMemberNode_AndSpecialize(PythonAbstractObjectGen.java:833)
from com.oracle.graal.python.builtins.objects.PythonAbstractObjectGen$InteropLibraryExports$Cached.invokeMember(PythonAbstractObjectGen.java:816)
from com.oracle.truffle.api.interop.InteropLibraryGen$CachedDispatch.invokeMember(InteropLibraryGen.java:3104)
from com.oracle.truffle.api.interop.LegacyToLibraryNode.sendInvoke(LegacyToLibraryNode.java:272)
from com.oracle.truffle.api.interop.ForeignAccess.sendInvoke(ForeignAccess.java:395)
Translated to internal error (RuntimeError)
Run with --verbose to see the full stack trace.
ruby>
After looking at the bottom stack frames, I'm assuming this could be an incompatibility between the old and the new interop, but it might as well just be a general interop issue in TruffleRuby.
A small guess: this is Ruby so Polyglot.import('d').maxlen calls a method maxlen (with no arguments). Polyglot.import('d')[:maxlen] is probably what you want. I tried, and that works.
Oh right, so maybe there's only an issue in GraalPython, which should indicate there's no such method instead of failing with an exception.
UnsupportedMessageException should never be rethrown, but always translated into a language specific error. In this case "method maxlen not found". So the problem is in Ruby here.
Indeed, this internal error message is suboptimal, I'll fix it.
In this case, I guess we should throw a NoMethodError since there is no maxlen method (there is a member maxlen but it's not invocable).
I think we are translating to a language-specific error aren't we? A Ruby RuntimeError, which is thrown as a TruffleException subclass, Ruby's RaiseException. The message just includes the original Java class name, which could be improved.
The most obvious fix gives:
ruby> Polyglot.import('d').maxlen
Message not supported. (NoMethodError)
at <ruby> <top (required)>(<shell>:1:0-26)
at <ruby> parsing-request(Unknown)
Is that good enough or do we want something that look exactly like a Ruby NoMethodError for the message too, but then doesn't indicate what the receiving language threw?
I'd make the Ruby no method error be the most prominent thing. If the interop error provides a message in addition, then you can put that in braces.
It should immediatly look familiar to Ruby users .
It is, this is standard Ruby error formatting.
Here is the error message in a Ruby-only context:
ruby> 3.foobar
undefined method `foobar' for 3:Integer
Did you mean? floor (NoMethodError)
at <ruby> <top (required)>(<shell>:1:0-7)
at <ruby> parsing-request(Unknown)
Not sure how consistent the error format is in Ruby, but maybe the error should look more like the following?
ruby> Polyglot.import('d').maxlen
undefined method `maxlen' for <foreign>
at <ruby> <top (required)>(<shell>:1:0-26)
at <ruby> parsing-request(Unknown)
Nonetheless, the solution you mentioned in https://github.com/oracle/truffleruby/issues/1690#issuecomment-493010598 would also be fine.
I merged my proposed fix from https://github.com/oracle/truffleruby/issues/1690#issuecomment-493010598 in 33c2fe41d432d5ee687ec76f4b1a2844f4bbf7cd, it will be in the next release.
We can certainly improve interop exceptions further, but I went for a straightforward fix here as we are doing a large interop refactoring currently.
@fniephaus Thank you for the report!
Great...that's perfect, thanks! Looking forward to the refactoring :)