You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ant.apache.org by bo...@apache.org on 2020/09/25 19:13:26 UTC

[ant] 03/03: enable Nashorn compatibility when running GraalVM JS

This is an automated email from the ASF dual-hosted git repository.

bodewig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ant.git

commit a83708498058dfe59a50d40a982050837b1d397d
Author: Stefan Bodewig <bo...@apache.org>
AuthorDate: Fri Sep 25 21:12:37 2020 +0200

    enable Nashorn compatibility when running GraalVM JS
    
    and add a magic property to disable it again
---
 WHATSNEW                                           |  8 +++-
 build.xml                                          | 46 ++++++++++++++++++-
 manual/Tasks/script.html                           |  7 +++
 manual/running.html                                |  9 ++++
 .../testcases/taskdefs/optional/script/graal.xml   | 28 ++++++++++++
 src/main/org/apache/tools/ant/MagicNames.java      | 12 +++++
 .../tools/ant/util/optional/JavaxScriptRunner.java | 15 +++++-
 .../script/graal/AbstractNashornCompatTest.java    | 53 ++++++++++++++++++++++
 .../script/graal/DefaultNashornCompatTest.java     | 25 ++++++++++
 .../script/graal/DisableNashornCompatTest.java     | 41 +++++++++++++++++
 .../script/graal/EnableNashornCompatTest.java      | 25 ++++++++++
 11 files changed, 266 insertions(+), 3 deletions(-)

diff --git a/WHATSNEW b/WHATSNEW
index 2632974..2ff4e0e 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -39,7 +39,13 @@ Other changes:
  * added some special code to support GraalVM JavaScript as
    javax.script scripting engine for JavaScript. In particular we
    relax some security settings of GraalVM so that scripts can access
-   Ant objects. See the script task manual for additional details.
+   Ant objects.
+
+   Also Ant enables Nashorn compatibility mode by default, you can
+   disable that by setting the magic Ant property
+   ant.disable.graal.nashorn.compat to true.
+
+   See the script task manual for additional details.
 
  * If the magic property ant.tmpdir hasn't been set and Ant can
    control the permissions of directories it creates it will create an
diff --git a/build.xml b/build.xml
index 4e157d6..3e75320 100644
--- a/build.xml
+++ b/build.xml
@@ -336,6 +336,10 @@
     </or>
   </selector>
 
+  <selector id="needs.graaljs">
+    <filename name="${optional.package}/script/graal/*"/>
+  </selector>
+
   <selector id="ant.launcher">
     <filename name="${ant.package}/launch/"/>
   </selector>
@@ -503,6 +507,9 @@
     <available property="javamail.present"
                classname="javax.mail.Transport"
                classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/>
+    <available property="graaljs.present"
+               classname="com.oracle.truffle.js.scriptengine.GraalJSScriptEngine"
+               classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/>
 
     <condition property="tests.and.ant.share.classloader">
       <or>
@@ -1870,7 +1877,41 @@ ${antunit.reports}
     </junitreport>
   </target>
 
-  <target name="junit-tests" depends="junit-batch,junit-single-test"/>
+  <target name="junit-tests" depends="junit-batch,graaljs-tests,junit-single-test"/>
+
+  <target name="graaljs-tests" depends="compile-tests,test-init"
+          if="graaljs.present">
+    <junit printsummary="${junit.summary}"
+           haltonfailure="${test.haltonfailure}"
+           fork="true"
+           forkmode="perTest"
+           tempdir="${build.dir}"
+           failureproperty="junit.failed"
+           errorproperty="junit.failed"
+           filtertrace="${junit.filtertrace}">
+      <sysproperty key="ant.home" value="${ant.home}"/>
+      <sysproperty key="build.classes.value" value="${build.classes.value}"/>
+      <sysproperty key="build.tests.value" value="${build.tests.value}"/>
+      <sysproperty key="offline" value="${offline}"/>
+      <sysproperty key="tests-classpath.value"
+                   value="${toString:tests-runtime-classpath}"/>
+      <sysproperty key="root" file="${basedir}"/>
+      <sysproperty key="build.compiler" value="${build.compiler}"/>
+      <sysproperty key="tests.and.ant.share.classloader"
+                   value="${tests.and.ant.share.classloader}"/>
+      <sysproperty key="java.io.tmpdir" file="${build.junit.tmpdir}"/>
+      <classpath>
+        <path refid="tests-runtime-classpath"/>
+        <pathelement location="${junit.collector.dir}"/>
+      </classpath>
+      <formatter type="xml"/>
+      <batchtest todir="${build.junit.xml}" unless="hasFailingTests">
+        <fileset dir="${src.junit}" excludes="**/Abstract*">
+          <selector refid="needs.graaljs" if="graaljs.present"/>
+        </fileset>
+      </batchtest>
+    </junit>
+  </target>
 
   <target name="junit-batch" depends="compile-tests,test-init" if="junit.batch">
 
@@ -1907,6 +1948,9 @@ ${antunit.reports}
           <exclude name="${taskdefs.package}/TestProcess.java"/>
           <exclude name="${optional.package}/splash/SplashScreenTest.java"/>
 
+          <!-- GraalVM JavaScript Nashorn compat tests influencing current JVM -->
+          <exclude name="${optional.package}/script/graal/"/>
+
           <!-- only run these tests if their required libraries are installed -->
           <selector refid="conditional-patterns"/>
 
diff --git a/manual/Tasks/script.html b/manual/Tasks/script.html
index e029cd9..32c2a91 100644
--- a/manual/Tasks/script.html
+++ b/manual/Tasks/script.html
@@ -293,6 +293,13 @@ compatibility script</a>: <code>load("nashorn:mozilla_compat.js");</code>.</p>
   Graal's <a href="https://github.com/graalvm/graaljs/blob/master/docs/user/NashornMigrationGuide.md">Nashorn
   Migration Guide</a> for more details.</p>
 
+<p>When using GraalVM JavaScript Ant will enable the
+  feature <code>polyglot.js.allowAllAccess</code> in order to allow
+  scripts to use Ant objects. By default it will also enable Nashorn
+  compatibility mode, but you can disable this by setting the magic
+  Ant property <code>ant.disable.graal.nashorn.compat</code>
+  to <code>true</code>.</p>
+
 <p>The <code>&lt;script&gt;</code> task populates the Project instance under the
 name <code class="code">project</code>, so we can use that reference. Another way is to use its
 given name or getting its reference from the task itself. The Project provides methods for accessing
diff --git a/manual/running.html b/manual/running.html
index 63647f8..bca2ea2 100644
--- a/manual/running.html
+++ b/manual/running.html
@@ -479,6 +479,15 @@ And I filtered out the <code>getPropertyHelper</code> access.</p>
   from within the build file.<br/>
   See also <a href="#tmpdir">Temporary Directories</a>.</td>
 </tr>
+<tr>
+  <td><code>ant.disable.graal.nashorn.compat</code></td>
+  <td>boolean (default <q>false</q>)</td>
+  <td><em>Since Ant 1.10.9</em><br/>
+  By default Ant will enable GraalVM JavaScript's Nashorn
+  compatibility mode for <code>script</code> and friends. You can
+  disable this beahvior by setting this property to <q>true</q>.<br/>
+  See also the <a href="Tasks/script.html">script task manual</a>.</td>
+</tr>
 </table>
 
 <p>
diff --git a/src/etc/testcases/taskdefs/optional/script/graal.xml b/src/etc/testcases/taskdefs/optional/script/graal.xml
new file mode 100644
index 0000000..42a69c5
--- /dev/null
+++ b/src/etc/testcases/taskdefs/optional/script/graal.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      https://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<project name="squares">
+  <target name="run-squares-test">
+    <script language="javascript" manager="javax"> <![CDATA[
+      for (i = 1; i <= 10; i++) {
+        echo = squares.createTask("echo");
+        echo.setMessage(i*i);
+        echo.perform();
+      }
+    ]]> </script>
+  </target>
+</project>
diff --git a/src/main/org/apache/tools/ant/MagicNames.java b/src/main/org/apache/tools/ant/MagicNames.java
index 8ced505..12fbcf7 100644
--- a/src/main/org/apache/tools/ant/MagicNames.java
+++ b/src/main/org/apache/tools/ant/MagicNames.java
@@ -347,5 +347,17 @@ public final class MagicNames {
      * @since Ant 1.10.9
      */
     public static final String AUTO_TMPDIR = "ant.auto.tmpdir";
+
+    /**
+     * Magic property that can be used to disable Nashorn compatibility mode when using GraalVM JavaScript as script
+     * engine.
+     *
+     * <p>Set this to "true" if you want to disable Nashorn compatibility mode.</p>
+     *
+     * Value: {@value}
+     * @since Ant 1.10.9
+     */
+    public static final String DISABLE_NASHORN_COMPAT = "ant.disable.graal.nashorn.compat";
+
 }
 
diff --git a/src/main/org/apache/tools/ant/util/optional/JavaxScriptRunner.java b/src/main/org/apache/tools/ant/util/optional/JavaxScriptRunner.java
index a9b565c..591744e 100644
--- a/src/main/org/apache/tools/ant/util/optional/JavaxScriptRunner.java
+++ b/src/main/org/apache/tools/ant/util/optional/JavaxScriptRunner.java
@@ -193,7 +193,10 @@ public class JavaxScriptRunner extends ScriptRunnerBase {
         if (keptEngine != null) {
             return keptEngine;
         }
-        ScriptEngine result =
+        if (languageIsJavaScript()) {
+            maybeEnableNashornCompatibility();
+        }
+        final ScriptEngine result =
             new ScriptEngineManager().getEngineByName(getLanguage());
         if (result == null && JavaEnvUtils.isAtLeastJavaVersion("15")
             && languageIsJavaScript()) {
@@ -219,6 +222,16 @@ public class JavaxScriptRunner extends ScriptRunnerBase {
         }
     }
 
+    private static final String ENABLE_NASHORN_COMPAT_IN_GRAAL = "polyglot.js.nashorn-compat";
+
+    private void maybeEnableNashornCompatibility() {
+        if (getProject() != null) {
+            System.setProperty(ENABLE_NASHORN_COMPAT_IN_GRAAL,
+                Project.toBoolean(getProject().getProperty(MagicNames.DISABLE_NASHORN_COMPAT))
+                ? "false" : "true");
+        }
+    }
+
     private final static List<String> JS_LANGUAGES = Arrays.asList("js", "javascript");
 
     private boolean languageIsJavaScript() {
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/AbstractNashornCompatTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/AbstractNashornCompatTest.java
new file mode 100644
index 0000000..25123d2
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/AbstractNashornCompatTest.java
@@ -0,0 +1,53 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.tools.ant.taskdefs.optional.script.graal;
+
+import org.apache.tools.ant.BuildFileRule;
+import org.apache.tools.ant.MagicNames;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
+
+public class AbstractNashornCompatTest {
+
+    private final String magicPropertyValue;
+
+    public AbstractNashornCompatTest(String magicPropertyValue) {
+        this.magicPropertyValue = magicPropertyValue;
+    }
+
+    @Rule
+    public BuildFileRule buildRule = new BuildFileRule();
+
+    @Before
+    public void setUp() {
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/script/graal.xml");
+        buildRule.getProject().setProperty(MagicNames.DISABLE_NASHORN_COMPAT, magicPropertyValue);
+    }
+
+    @Test
+    public void runSquaresTest() {
+        buildRule.executeTarget("run-squares-test");
+        assertThat("Expecting the square of 7 to be logged", buildRule.getLog(),
+            containsString("49"));
+    }
+}
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/DefaultNashornCompatTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/DefaultNashornCompatTest.java
new file mode 100644
index 0000000..a5c1771
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/DefaultNashornCompatTest.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.tools.ant.taskdefs.optional.script.graal;
+
+public class DefaultNashornCompatTest extends AbstractNashornCompatTest {
+
+    public DefaultNashornCompatTest() {
+        super(null);
+    }
+}
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/DisableNashornCompatTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/DisableNashornCompatTest.java
new file mode 100644
index 0000000..808bdee
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/DisableNashornCompatTest.java
@@ -0,0 +1,41 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.tools.ant.taskdefs.optional.script.graal;
+
+import org.apache.tools.ant.BuildException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class DisableNashornCompatTest extends AbstractNashornCompatTest {
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    public DisableNashornCompatTest() {
+        super("true");
+    }
+
+    @Test
+    @Override
+    public void runSquaresTest() {
+        thrown.expect(BuildException.class);
+        thrown.expectMessage("TypeError");
+        super.runSquaresTest();
+    }
+}
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/EnableNashornCompatTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/EnableNashornCompatTest.java
new file mode 100644
index 0000000..2161b6f
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/script/graal/EnableNashornCompatTest.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.tools.ant.taskdefs.optional.script.graal;
+
+public class EnableNashornCompatTest extends AbstractNashornCompatTest {
+
+    public EnableNashornCompatTest() {
+        super("false");
+    }
+}