Skip to content
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

Merged
merged 2 commits into from Jan 21, 2019

Conversation

JaroslavTulach
Copy link

@JaroslavTulach JaroslavTulach commented Nov 6, 2018

Introducing org.netbeans.api.scripting API to wrap access to javax.script.ScriptEngineManager and provide necessary extensions to incorporate the Truffle language registrations into the system and expose them through the javax.script interfaces. That way the NetBeans modules can use API that works on any JDK and still access functionality that is provided by GraalVM.

@JaroslavTulach
Copy link
Author

@JaroslavTulach JaroslavTulach commented Nov 27, 2018

Ready for review, I'd say. Please take a look. Thanks. CCing @tzezula, @thurka, @timfel, @sdedic

@junichi11
Copy link
Member

@junichi11 junichi11 commented Dec 4, 2018

It seems that there are conflicts.

<code-name-base>org.netbeans.api.scripting</code-name-base>
<module-dependencies>
<dependency>
<code-name-base>org.netbeans.modules.nbjunit</code-name-base>
Copy link
Member

@sdedic sdedic Dec 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test-dependency

# 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
Copy link
Member

@sdedic sdedic Dec 4, 2018

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.

Copy link
Author

@JaroslavTulach JaroslavTulach Dec 5, 2018

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>
Copy link
Member

@sdedic sdedic Dec 4, 2018

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
Copy link
Member

@sdedic sdedic Dec 4, 2018

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 ?

Copy link
Author

@JaroslavTulach JaroslavTulach Jan 16, 2019

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
Copy link
Member

@sdedic sdedic Dec 4, 2018

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.

Copy link
Author

@JaroslavTulach JaroslavTulach Jan 16, 2019

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;
Copy link
Member

@sdedic sdedic Dec 4, 2018

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.

Copy link
Author

@JaroslavTulach JaroslavTulach Jan 17, 2019

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);
Copy link
Member

@sdedic sdedic Dec 4, 2018

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

Copy link
Author

@JaroslavTulach JaroslavTulach Jan 17, 2019

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);
Copy link
Member

@sdedic sdedic Dec 4, 2018

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 ?

Copy link
Author

@JaroslavTulach JaroslavTulach Jan 16, 2019

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);
Copy link
Member

@sdedic sdedic Dec 4, 2018

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 ?

Copy link
Author

@JaroslavTulach JaroslavTulach Jan 16, 2019

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;
Copy link
Member

@sdedic sdedic Dec 4, 2018

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 ?

Copy link

@timfel timfel Dec 5, 2018

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

Copy link
Member

@sdedic sdedic Dec 5, 2018

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.

Copy link
Member

@emilianbold emilianbold left a comment

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());
Copy link
Member

@emilianbold emilianbold Dec 5, 2018

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?

Copy link
Author

@JaroslavTulach JaroslavTulach Dec 5, 2018

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();
Copy link
Member

@emilianbold emilianbold Dec 5, 2018

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?

Copy link
Author

@JaroslavTulach JaroslavTulach Dec 5, 2018

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
Copy link
Member

@emilianbold emilianbold Dec 5, 2018

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.org

This 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.

Copy link
Author

@JaroslavTulach JaroslavTulach Dec 5, 2018

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
Copy link
Member

@emilianbold emilianbold Dec 5, 2018

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?

Copy link
Author

@JaroslavTulach JaroslavTulach Dec 5, 2018

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
Copy link
Member

@emilianbold emilianbold Dec 5, 2018

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>

Copy link
Author

@JaroslavTulach JaroslavTulach Jan 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* under the License.
*/
'Use Scripting.createManager()':
new javax.script.ScriptEngineManager($$anything$$)
Copy link
Member

@emilianbold emilianbold Dec 5, 2018

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?

Copy link
Author

@JaroslavTulach JaroslavTulach Dec 5, 2018

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);
Copy link
Member

@emilianbold emilianbold Dec 5, 2018

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...

Copy link
Author

@JaroslavTulach JaroslavTulach Dec 5, 2018

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)
Copy link
Member

@emilianbold emilianbold Dec 5, 2018

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?

Copy link
Author

@JaroslavTulach JaroslavTulach Dec 5, 2018

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.

Copy link
Member

@emilianbold emilianbold Dec 11, 2018

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...

Copy link
Author

@JaroslavTulach JaroslavTulach Dec 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. If we ever want to bundle Graal.js and use it on regular (e.g. non-GraalVM) JVM then this setup would be wrong. So far I was only testing on either regular JVM (the engine missing and disabled) or GraalVM (the API classes and the engine present).

Copy link
Member

@emilianbold emilianbold Dec 27, 2018

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) ?

Copy link
Author

@JaroslavTulach JaroslavTulach Jan 16, 2019

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.

@entlicher
Copy link
Contributor

@entlicher entlicher commented Jan 16, 2019

Concerning debugger it looks fine to me.
truffle-sl is used in tests only. If it builds fine, it does not matter that it comes from rc6. It might require update in the future if truffle-api removes possible deprecations used in SL, if any.

@JaroslavTulach
Copy link
Author

@JaroslavTulach JaroslavTulach commented Jan 17, 2019

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) {
Copy link
Author

@JaroslavTulach JaroslavTulach Jan 18, 2019

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();
Copy link
Author

@JaroslavTulach JaroslavTulach Jan 18, 2019

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

Copy link
Contributor

@jlahoda jlahoda Jan 18, 2019

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.

@matthiasblaesing
Copy link
Contributor

@matthiasblaesing matthiasblaesing commented Jan 18, 2019

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.

@jtulach
Copy link
Contributor

@jtulach jtulach commented Jan 19, 2019

I'll squash the changes on Monday and I leave out changes to platform/core.network out of the merge per @jlahoda and @matthiasblaesing request.

@JaroslavTulach JaroslavTulach force-pushed the ScriptingAPI branch 2 times, most recently from c4fe20a to 77968e6 Compare Jan 21, 2019
…ython, Ruby, etc. script engines. Using that API to integrate Graal.js as the default JavaScript engine for the IDE.
@JaroslavTulach JaroslavTulach merged commit 483e245 into apache:master Jan 21, 2019
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants