blob: b299b769316b07aad2c4d66507d021137216db47 [file] [log] [blame]
// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.rewrite;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.StringUtils;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class JavaScriptScriptEngineTest extends ScriptEngineTestBase {
private final TestParameters parameters;
@Parameterized.Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters().withAllRuntimesAndApiLevels().build();
}
public JavaScriptScriptEngineTest(TestParameters parameters) {
this.parameters = parameters;
}
private static String EXPECTED_RHINO_OUTPUT = StringUtils.lines("Mozilla Rhino", "42");
private static String EXPECTED_NASHORN_OUTPUT = StringUtils.lines("Oracle Nashorn", "42");
@Test
public void testD8() throws IOException, CompilationFailedException, ExecutionException {
assumeTrue("Only run D8 for dex backend", parameters.isDexRuntime());
testForD8()
.addInnerClasses(JavaScriptScriptEngineTest.class)
.setMinApi(parameters.getApiLevel())
.apply(this::addRhinoForAndroid)
.compile()
.run(parameters.getRuntime(), TestClassWithExplicitRhinoScriptEngineRegistration.class)
.assertSuccessWithOutput(EXPECTED_RHINO_OUTPUT);
}
@Test
public void testR8() throws IOException, CompilationFailedException, ExecutionException {
testForR8(parameters.getBackend())
.addInnerClasses(JavaScriptScriptEngineTest.class)
.addKeepMainRule(TestClass.class)
.setMinApi(parameters.getApiLevel())
.apply(
b -> {
if (parameters.isDexRuntime()) {
addRhinoForAndroid(b);
addKeepRulesForAndroidRhino(b);
b.allowDiagnosticWarningMessages();
}
})
.compile()
.assertAllWarningMessagesMatch(
anyOf(
containsString("Missing class:"),
containsString("required for default or static interface methods desugaring"),
equalTo("Resource 'META-INF/MANIFEST.MF' already exists.")))
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutput(
parameters.isCfRuntime() ? EXPECTED_NASHORN_OUTPUT : EXPECTED_RHINO_OUTPUT);
}
static class TestClass {
public final ScriptEngineManager manager = new ScriptEngineManager();
public void run() throws Exception {
ScriptEngine engine = manager.getEngineByMimeType("text/javascript");
System.out.println(engine.getFactory().getEngineName());
runJavaScript(engine);
}
public void runJavaScript(ScriptEngine engine) throws Exception {
// Add a simple JavaScript function and call it.
engine.eval("function add(x, y) { return x + y }");
Object fortyTwo = engine.eval("add(40, 2)");
// Rhino and Nashorn in JDK8 returns a Double. Nashorn in JDK9 and JDK11 returns an Integer.
if (fortyTwo instanceof Double) {
System.out.println(((Double) fortyTwo).intValue());
} else if (fortyTwo instanceof Integer) {
System.out.println(fortyTwo);
} else {
System.out.println("Unexpected");
}
}
public static void main(String[] args) throws Exception {
new TestClass().run();
}
}
static class TestClassWithExplicitRhinoScriptEngineRegistration extends TestClass {
public TestClassWithExplicitRhinoScriptEngineRegistration() throws Exception {
// D8 does not handle META-INF/services, it just produces dex files, so register
// the Rhino engine directly.
manager.registerEngineMimeType(
"text/javascript",
(ScriptEngineFactory)
(Class.forName("com.sun.script.javascript.RhinoScriptEngineFactory")
.getConstructor()
.newInstance()));
}
public static void main(String[] args) throws Exception {
new TestClassWithExplicitRhinoScriptEngineRegistration().run();
}
}
}