New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enhanced wrapper for Scripting API #1011
Conversation
|
It seems that there are conflicts. |
platform/api.scripting/src/org/netbeans/modules/scripting/WriterOutputStream.java
Outdated
Show resolved
Hide resolved
| <code-name-base>org.netbeans.api.scripting</code-name-base> | ||
| <module-dependencies> | ||
| <dependency> | ||
| <code-name-base>org.netbeans.modules.nbjunit</code-name-base> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test-dependency
nbbuild/travis/scripting.sh
Outdated
| # under the License. | ||
|
|
||
| BASE=graalvm-ce-1.0.0-rc9 | ||
| URL=https://github.com/oracle/graal/releases/download/vm-1.0.0-rc9/$BASE-linux-amd64.tar.gz |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is rather ugly platform (amd64) dependency for the CI build.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The CI build runs on 64bit Intel machines. What other download you'd use?
| <apichanges> | ||
| <apidefs> | ||
| <apidef name="scripting_api">Scripting API</apidef> | ||
| <apidef name="scripting_spi">Scripting API</apidef> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scripting SPI
| # KIND, either express or implied. See the License for the | ||
| # specific language governing permissions and limitations | ||
| # under the License. | ||
| 07B63F4902CA51B574EA892D5D5E8088B8FBF97A org.graalvm:graal-sdk:1.0.0-rc6 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be better to upgrade to SDK RC9, given that Travis actually downloads RC9 runtime ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've created libs.graalsdk, libs.truffleapi modules and used the latest RC10. I have modified debugger.jpda.truffle to use these modules, @entlicher please verify it is OK.
| # specific language governing permissions and limitations | ||
| # under the License. | ||
|
|
||
| OpenIDE-Module-Name=Scripting API Wrapper |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be probably more entries if the module is AutoUpdate-Show-In-Client: true so it's correctly listed in updates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably better to hide the module: b5e58fb
|
|
||
| @Override | ||
| public Object invokeMethod(Object thiz, String name, Object... args) throws ScriptException, NoSuchMethodException { | ||
| final Value thisValue = (Value) thiz; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw ScriptException rather than CCE if thiz is not a Value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea: 2ecb7b9
| public Object invokeMethod(Object thiz, String name, Object... args) throws ScriptException, NoSuchMethodException { | ||
| final Value thisValue = (Value) thiz; | ||
| Value fn = thisValue.getMember(name); | ||
| Value result = fn.execute(args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider throwing NoSuchMethodException if fn is !canExecute
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that would be more consistent. Implemented in b49167a
| @Override | ||
| public <T> T getInterface(Class<T> clasz) { | ||
| try { | ||
| return getInterface(evalImpl(getContext(), "this"), clasz); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a token valid for all Graal-provided languages ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, not at all. There is however no generic way to obtain the global object as such the current version is using getPolyglotBindings() - e.g. only exported values are visible.
| return null; | ||
| } | ||
| if (result.isNumber()) { | ||
| return result.as(Number.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't further classification using fitsInByte etc needed ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it? I don't know. Any example you have in mind?
|
|
||
| @Override | ||
| public String getMethodCallSyntax(String arg0, String arg1, String... arg2) { | ||
| return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be a nice request/PR for Truffle :) and Polyglot API in Graal project. Who else should know about the language syntax ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What exactly do you need here? We're in the process (oracle/graal#764) of adding API facilities for getting "completion characters" (. in many languages, sometimes ->) and "signature characters" (( in many languages) to get autocomplete and signature completion working. Maybe it would make sense to consider this use case in the PR as well, but we'd need to know what kind of "syntax" you need to create here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something which would allow to satisfy contract of ScriptEngineFactory in a lang-independent way so it can be bridged to standard Scripting APIs here, like the Polyglot Context eval* methods are.
Also note the other get* code construction helper methods in the scripting API.
I'm a bit puzzled by this commit. ScriptEngineManager is supposed to be dynamic enough but apparently we still need to wrap it at Platform level for actual modules. It would be nice if the JDK would be fixed so all these classes that rely on the service provider mechanism can actually run properly in a dynamic module system.
I also don't understand why we need the Graal dependency or the Graal service factory. These should be imho in a separate graal.scripting module which I'm not even certain needs to be part of platform so soon.
| @@ -242,7 +240,7 @@ protected static ScriptEngine getScriptEngine(FileObject fo) { | |||
| } catch (ClassNotFoundException ex) { | |||
| Exceptions.printStackTrace(ex); | |||
| } | |||
| manager = new ScriptEngineManager(loader != null ? loader : Thread.currentThread().getContextClassLoader()); | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is loader ignored here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The classloader logic is handled centrally in Scripting.createManager().
| @@ -2212,8 +2209,7 @@ private static ScriptEngine engine(FileObject fo) { | |||
| if (obj instanceof String) { | |||
| synchronized (GeneratorUtilities.class) { | |||
| if (manager == null) { | |||
| ClassLoader loader = Lookup.getDefault().lookup(ClassLoader.class); | |||
| manager = new ScriptEngineManager(loader != null ? loader : Thread.currentThread().getContextClassLoader()); | |||
| manager = Scripting.createManager(); | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, why is the loader logic ignored now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The classloader logic is handled centrally in Scripting.createManager().
| @@ -17,3 +17,4 @@ | |||
| A7674A6D78B7FEA58AF76B357DAE6EA5E3FDFBE9 apitest-70.jar | |||
| 16398550402B27F81CD0D508CEF54B3E47A4A6DA org.apache.rat:apache-rat:0.12 | |||
| AB396EE119BFAD809CC9F09950CC22E2BCE2FE35 langtools-9.zip | |||
| E32B3483FBF362C92088CB79E9F1F161F3F64A21 org.apidesign.javadoc:codesnippet-doclet:0.30 | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-1
According to https://search.maven.org/artifact/org.apidesign.javadoc/codesnippet-doclet/0.31/jar this is GPL 3:
Codesnippet Javadoc Doclet
Copyright (C) 2015-2018 Jaroslav Tulach - jaroslav.tulach@apidesign.orgThis program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3.0 of the License.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a build time only dependency. The codesnippet is used when generating Javadoc.
| Source: https://github.com/jtulach/codesnippet4javadoc/ | ||
| Description: Javadoc doclet to include real code snippets in the documentation | ||
| Origin: apidesign.org | ||
| Type: compile-time |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, so we are supposed to accept it since it's only compile time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. It is compile time and no Apache code is linked to that library. No Apache code is derived work of that library. Also, in the readme of the codesnippet4javadoc I explicitly allow anyone to use the tool to generate Javadoc for any code of any license.
|
|
||
| Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. | ||
|
|
||
| The Universal Permissive License (UPL), Version 1.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to https://search.maven.org/artifact/org.graalvm/graal-sdk/1.0.0-rc6/jar I see a different license:
<name>GNU General Public License, version 2, with the Classpath Exception</name> <url>http://openjdk.java.net/legal/gplv2+ce.html</url>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in version RC10: https://search.maven.org/artifact/org.graalvm.sdk/graal-sdk/1.0.0-rc10/jar
| * under the License. | ||
| */ | ||
| 'Use Scripting.createManager()': | ||
| new javax.script.ScriptEngineManager($$anything$$) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the hint also ignores any class loader?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. The new code is going to use the NetBeans classloader that sees all the registrations.
| for (EngineProvider p : Lookup.getDefault().lookupAll(EngineProvider.class)) { | ||
| extra.addAll(p.factories()); | ||
| } | ||
| ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So Scripting has a similar logic wrt ClassLoader. OK...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. The Scripting class is NetBeans aware and as such it can handle the classloading logic properly at a single place.
| import org.netbeans.spi.scripting.EngineProvider; | ||
| import org.openide.util.lookup.ServiceProvider; | ||
|
|
||
| @ServiceProvider(service = EngineProvider.class) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the Graal Engine Provider be in a separate module?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It used to be. It got merged in 818830a after in office discussion with Sváťa and Tomáš Zezula.
The needed org.graalvm.polyglot types are provided on bootclasspath when running on the GraalVM. Having them in the same module is similar and seemed OK as no additional runtime cost/weight of a module is paid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this wrong somehow. So you manage to compile those classes importing org.graalvm.* because you have a compile-time dependency on the Graal SDK but then I assume you rely that those classes will never be loaded by a module system classloader unless on the Graal VM?
Having compiled code that cannot be loaded at runtime feels like a broken dependency to me...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still find this an abuse of the module system. Why compile the code is this weird way, add a compile time dependency on Graal and have .class files that are un-loadable when we could have a separate module for people to load when Graal is there?
Maybe have a token or something for GraalVM (something for OpenIDE-Module-Java-Dependencies perhaps) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @emilianbold (and also @jlahoda): per your request I moved the GraalVM specific part (including the documentation) into libs.graalsdk module. Now I expect your approvals. Thank you.
|
Concerning debugger it looks fine to me. |
|
I think all the comments have been addressed. I have an approval (more is welcomed). I'll squash and integrate the change soon. |
| @@ -172,6 +176,22 @@ public void delayAnsweringBy(long msWait ) { | |||
| return null; | |||
| } | |||
|
|
|||
| @Override | |||
| Callable<InetAddress[]> createDnsTimeoutTask(String host) { | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lbruun, please take a look. Hopefully I changed no semantics, but now the test passes on JDK11. Instead of injecting something into sun.*.net.* packages, I inject different implementation of createDnsTimeoutTask in the test.
| // - since Java 8 - it will be a Nashorn engine. | ||
| ScriptEngineManager factory = new ScriptEngineManager(); | ||
| return factory.getEngineByName("JavaScript"); | ||
| ScriptEngineManager manager = Scripting.createManager(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using engine from libs.graaljs module, if it is available. Otherwise falling back to default JavaScript engine. No special treatment needed, as all Java objects are wrapped into appropriate JavaScript function closures. CCing @lbruun
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am really not sure about the removal of special-casing for Nashorn. I think I have a counter example (for Nashorn at least). Please let me know which venue is appropriate to discuss that.
|
Please try to break this PR into reviewable parts. There are now 58 commits and 114 changed files Especially the the changes to the proxy selector infrastructure should be separated, as that is security critical. |
|
I'll squash the changes on Monday and I leave out changes to |
c4fe20a
to
77968e6
Compare
…ython, Ruby, etc. script engines. Using that API to integrate Graal.js as the default JavaScript engine for the IDE.
Introducing
org.netbeans.api.scriptingAPI to wrap access tojavax.script.ScriptEngineManagerand provide necessary extensions to incorporate the Truffle language registrations into the system and expose them through thejavax.scriptinterfaces. That way the NetBeans modules can use API that works on any JDK and still access functionality that is provided by GraalVM.