Developer API docs
Tal Liron
tal.liron at threecrickets.com
Wed Oct 21 18:38:12 UTC 2015
Thank you for your reply, Sundar.
Unfortunately, your suggestions are insufficient.
In the BSON translator, I do not have access to the script engine at
all. It might not even be created: after all, the BSON translator can be
invoked by Nashorn directly, not in JSR-223 mode.
Likewise, you have not addressed much more of what I write about: access
to Script, Source, Context, etc.
I understand that you do not want to have to support internal APIs. I
merely wanted to prove to you that there is a cost in doing so: many
powerful things can only be achieved by access to those APIs. This means
that various 3rd party products might break with newer versions of Nashorn.
This is not the end of the world: many libraries, of course, break
dependent products, even in regards to public APIs.
Still, I hope you can read my original email in depth and think more
about what I'm trying to do. Perhaps you will agree that some of those
APIs could benefit from being public, or suggest other solutions for me.
On my end, I will continue to maintain my code as is, even if it uses
internal APIs, because it allows me to use Nashorn for some very cool
projects.
-Tal
On 10/15/2015 09:56 PM, Sundararajan Athijegannathan wrote:
> Hi Tal Liron,
>
> Sorry about missing reply for this email. I somehow remember replying
> similar nashorn internal usage email.
> It is difficult maintain all of jdk.nashorn.internal.* between
> versions. Also, with security manager around, jdk.nashorn.internal.*
> are not accessible without explicit 'package access'
> RuntimePermission. In addition, with jdk9, nashorn module exports only
> jdk.nashorn.api.* packages. i.e., even without any security manager,
> user code won't be able to access nashorn internal implementation
> classes. It is possible to use jdk.nashorn.api.scripting.JSObject to
> get constructors and create objecs.
>
> JSObject numberConstructor = (JSObject) engine.eval("Number");
> JSObject numberObj = numberConstructor.newObject();
>
> Is it not possible to work with these? Please check out latest 8u-dev
> code. Mostly explicit wrap/unwrap won't be required from user's code.
>
> Thanks,
> -Sundar
>
> On 10/15/2015 10:21 PM, Tal Liron wrote:
>> Hey guys, nobody ever responded to my message...
>>
>> Do you really think that my usage of these internal Nashorn APIs is
>> so unwarranted?
>>
>> I tried to prove that some useful libraries need to use Nashorn APIs
>> that some of you insist should not be made public.
>>
>> On 07/06/2015 09:10 PM, Tal Liron wrote:
>>> Hi Atilla (and Sundar and everyone else, really),
>>>
>>> You asked which Nashorn APIs I'm using that are not documented. I
>>> will reply in full detail.
>>>
>>> For the BSON/JSON codecs, the most important thing is to access the
>>> NativeBoolean, NativeNumber, NativeArray, ConsString, Undefined,
>>> etc., classes. This allows the codecs to check for these classes
>>> incoming, and also to easily create instances of them using their
>>> constructor() static method.
>>>
>>> ScriptObject has no constructor(), so I use
>>> Global.newEmptyInstance(). (By the way: NativeDate and NativeArray
>>> name the method construct() instead of constructor(). I assume this
>>> is a consistency mistake.)
>>>
>>> But I also need to access their data. This means get()/set() for
>>> NativeScriptObject and NativeArray, getOwnKeys(), getArray() (which
>>> means I need access to the ArrayData class), and also getTime() for
>>> NativeData. NativeRegExp is a bit harder, but I use get("source"),
>>> get("multiline"), etc.
>>>
>>> (In Rhino, some of these classes are actually private! This required
>>> an awkward workaround: I do a string equality check on the
>>> classname. That's neither efficient nor portable, though more
>>> "dynamic", I guess. Also, for these classes I can use
>>> Context.newObject() to create instances by JS name, for example
>>> "RegExp". Then I can do ScriptableObject.callMethod() to access
>>> their internals. So, there are workarounds to not being to able to
>>> access them.)
>>>
>>> ScriptObjectMirror is awkward. Though it's stable and documented,
>>> the issue with unwrap() is that it needs a global. Documented, but
>>> of course unclear what to do! For me, this actually means calling
>>> Context.getGlobal(), which is not publicly documented. (Another
>>> issue is that, of course, unwrap won't work for other globals. This
>>> has created difficulties in some threaded environments in which
>>> multiple globals are used intentionally. More on that below.)
>>>
>>> So much for BSON/JSON. The Scripturian implementation of Nashorn is
>>> much more complex. As you may know, Scripturian is a rethinking of
>>> and alternative to JSR-223, so it has to do much of the same work.
>>>
>>> Scripturian works by purposely creating different global instances
>>> for each "execution context" (which *can* be a thread, but doesn't
>>> have to be: it's an abstraction over, well, execution contexts). I
>>> use Context.createGlobal(), and set it via Context.setGlobal().
>>>
>>> We then need to compile scripts in the Context, so I use
>>> Source.sourceFor() and Context.compileScript(), which returns a
>>> ScriptFunction, so I also need access to that. Compilations errors
>>> are via Context.getErrorManager(), so I need access to ErrorManager.
>>> To run the scripts, I use ScriptRuntime.apply(). A small fix I need
>>> to add is that Nashorn's NativeArray does not support
>>> java.util.List, so if an array is returned from apply(), I call
>>> NativeJava.to() to get list access. Thats's just a bit friendlier
>>> for users of Scripturian, who are otherwise agnostic about
>>> implementation specifics.
>>>
>>> There's an important issue here: remember, there might be many
>>> different globals, but of course I want them all to use the same
>>> code cache, which is stored in the Context. So, I use one singleton
>>> Context and switch globals via Context.setGlobal(). To create a
>>> Context, I also need access to Options. A limitation in Nashorn is
>>> that I can't change stdout and stderr after I create the Context
>>> (Scripturian allows different onces per ExecutionContext), so my
>>> workaround is to use a custom Writer wrapper class that underneath
>>> delegates to the correct "real" Writers (I use the same mechanism
>>> for a few other Scripturian language engines, too).
>>>
>>> I grumbled here before that I have no programmatic access to the
>>> code cache. Behind the scenes, ScriptFunction might retrieve from
>>> the cache instead of being compiled. I can control the cache base
>>> location via the "nashorn.persistent.code.cache" system property,
>>> but it's unfortunate that I can't control the structure and naming
>>> the way I can with other languages supported by Scripturian. In
>>> particular, the problem is that it's a global property for the whole
>>> JVM, whereas compilation and caching location is ideally controlled
>>> per ExecutionContext in Scripturian. This makes Nashorn support in
>>> Scripturian a bit more limited.
>>>
>>> Finally, for errors during execution, I use NashornException
>>> (documented!) to extract specific information into Scripturian's
>>> more generic ExecutionException.
>>>
>>> Small extras: I use Version.version() and
>>> NashornScriptEngineFactory.getLanguageVersion() to get version data.
>>>
>>> I think that's everything! Of course, I also had to "reverse
>>> engineer" much of this (=read a lot of code) and work around many
>>> quirks (and big differences to Rhino's implementation) before
>>> streamlining it down to just these few classes. (I tried to work
>>> around the caching limitations, but gave up due to its complexity.
>>> Also, I think some of the key classes I would need are private.) I
>>> did my best not to delve to much into internals, but I hope I made
>>> it clear to you that it would have been impossible to achieve all
>>> the above goals without it.
>>>
>>> -Tal
>>>
>>> On 07/06/2015 04:18 AM, Attila Szegedi wrote:
>>>> What APIs are you using, BTW? Just curious if I can suggest an
>>>> alternative approach, or even consider if something you use should
>>>> be publicly supported.
>>>
>>
>
More information about the nashorn-dev
mailing list