diff --git a/pom.xml b/pom.xml index 9bcf1194..ec63802e 100644 --- a/pom.xml +++ b/pom.xml @@ -282,6 +282,19 @@ 3.1 + + + + org.graalvm.sdk + graal-sdk + 21.3.0 + + + org.graalvm.js + js + 21.3.0 + + diff --git a/src/test/java/dk/kb/netarchivesuite/solrwayback/javascript/JavascriptTests.java b/src/test/java/dk/kb/netarchivesuite/solrwayback/javascript/JavascriptTests.java index 87db30c0..b401e660 100644 --- a/src/test/java/dk/kb/netarchivesuite/solrwayback/javascript/JavascriptTests.java +++ b/src/test/java/dk/kb/netarchivesuite/solrwayback/javascript/JavascriptTests.java @@ -2,44 +2,26 @@ import dk.kb.netarchivesuite.solrwayback.util.FileUtil; -import org.openjdk.nashorn.api.scripting.JSObject; -import org.junit.Before; +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Engine; +import org.graalvm.polyglot.Value; import org.junit.Test; -import javax.script.Invocable; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** - * Unittest method to call the query parser defined in the VUE typescript. The method has been copied to a new file and is now pure javascript. + * Unittest method to call the query parser defined in the VUE typescript. + * The method has been copied to a new file and is now pure javascript. */ public class JavascriptTests { - //The following two string will patch the java nashorn (ECMA version 5) engine to support the includes function on string and arrays (introduced in EMCA version 6) - // Copied from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes#Polyfill - public static final String NASHORN_POLYFILL_STRING_PROTOTYPE_INCLUDES = "if (!String.prototype.includes) { Object.defineProperty(String.prototype, 'includes', { value: function(search, start) { if (typeof start !== 'number') { start = 0 } if (start + search.length > this.length) { return false } else { return this.indexOf(search, start) !== -1 } } }) }"; - // Copied from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes#Polyfill - public static final String NASHORN_POLYFILL_ARRAY_PROTOTYPE_INCLUDES = "if (!Array.prototype.includes) { Object.defineProperty(Array.prototype, 'includes', { value: function(valueToFind, fromIndex) { if (this == null) { throw new TypeError('\"this\" is null or not defined'); } var o = Object(this); var len = o.length >>> 0; if (len === 0) { return false; } var n = fromIndex | 0; var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); function sameValueZero(x, y) { return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y)); } while (k < len) { if (sameValueZero(o[k], valueToFind)) { return true; } k++; } return false; } }); }"; - - private Invocable inv; - - @Before - public void initScripts() throws Exception { - ScriptEngine scriptEngine = getJavascriptScriptEnginePatched(); - scriptEngine.eval(extractQueryChecker()); - inv = (Invocable) scriptEngine; - } - @Test public void testBooleanCase() throws Exception { assertClean("foo AND bar"); @@ -104,11 +86,6 @@ public void testMix() throws Exception { assertWarning("foo:‟bar‟ AND foo:bar:zoo", "use simple quote signs", "Two colons without quote signs"); } - public void disabledtestExampleQuery() throws Exception { - String query="abc ( def AND or and [ def"; - List results = getQueryParseResultFromJavascript(query); - System.out.println(results); - } /** * Calls {@code checkQueryForBadSyntax} with {@code query} and checks that the result is the {@code expectedMessage}. @@ -116,16 +93,24 @@ public void disabledtestExampleQuery() throws Exception { * @param expectedContains the response from the sanity checker should contain this text. */ private void assertWarning(String query, String... expectedContains) throws Exception { - String warning = getQueryParseResultFromJavascript(query).toString(); - if (expectedContains.length == 0) { // Any warning - assertFalse("Sanity checking the query '" + query + "' should deliver a warning", - warning.isEmpty()); - } - - for (String expected: expectedContains) { - assertTrue("Sanity checking the query '" + query + "' should deliver a warning containing '" + - expected + "' but delivered '" + warning + "'", - warning.contains(expected)); + // Defining the engine explicitly so that testing doesn't warn about no runtime compilation of JavaScript + Engine engine = Engine.newBuilder().option("engine.WarnInterpreterOnly", "false").build(); + try (Context context = Context.newBuilder("js").engine(engine).allowIO(true).build()) { + + String jsCode = extractQueryChecker(); + context.eval("js", jsCode); + + String warning = getQueryParseResultFromJavascript(query, context).toString(); + if (expectedContains.length == 0) { // Any warning + assertFalse("Sanity checking the query '" + query + "' should deliver a warning", + warning.isEmpty()); + } + + for (String expected : expectedContains) { + assertTrue("Sanity checking the query '" + query + "' should deliver a warning containing '" + + expected + "' but delivered '" + warning + "'", + warning.contains(expected)); + } } } @@ -134,25 +119,21 @@ private void assertWarning(String query, String... expectedContains) throws Exce * @param query a query as used in SolrWayback. */ private void assertClean(String query) throws Exception { - String warning = getQueryParseResultFromJavascript(query).toString(); - assertTrue("Sanity checking the query '" + query + "' should deliver no warning but returned'" + - warning + "'", "[]".equals(warning)); - } - - private List getQueryParseResultFromJavascript(String query) throws Exception{ - JSObject obj = (JSObject) inv.invokeFunction("checkQueryForBadSyntax", query); - return obj.values().stream().map(Object::toString).collect(Collectors.toList()); + // Defining the engine explicitly so that testing doesn't warn about no runtime compilation of JavaScript + Engine engine = Engine.newBuilder().option("engine.WarnInterpreterOnly", "false").build(); + try (Context context = Context.newBuilder("js").engine(engine).allowIO(true).build()) { + String jsCode = extractQueryChecker(); + context.eval("js", jsCode); + + String warning = getQueryParseResultFromJavascript(query, context).toString(); + assertTrue("Sanity checking the query '" + query + "' should deliver no warning but returned'" + + warning + "'", "[]".equals(warning)); + } } - private static ScriptEngine getJavascriptScriptEnginePatched() throws Exception { - final ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); - final ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("nashorn"); - - //Define the .includes function in the script engine. - scriptEngine.eval(NASHORN_POLYFILL_ARRAY_PROTOTYPE_INCLUDES); - scriptEngine.eval(NASHORN_POLYFILL_STRING_PROTOTYPE_INCLUDES); - - return scriptEngine; + private Value getQueryParseResultFromJavascript(String query, Context context){ + Value checkQueryForBadSyntax = context.getBindings("js").getMember("checkQueryForBadSyntax"); + return checkQueryForBadSyntax.execute(query); } /**