diff --git a/qqq-language-support-javascript/pom.xml b/qqq-language-support-javascript/pom.xml
index 0210a4a8..67c7322b 100644
--- a/qqq-language-support-javascript/pom.xml
+++ b/qqq-language-support-javascript/pom.xml
@@ -47,9 +47,14 @@
- org.openjdk.nashorn
- nashorn-core
- 15.4
+ org.graalvm.js
+ js
+ 22.3.0
+
+
+ org.graalvm.js
+ js-scriptengine
+ 22.3.0
diff --git a/qqq-language-support-javascript/src/main/java/com/kingsrook/qqq/languages/javascript/QJavaScriptExecutor.java b/qqq-language-support-javascript/src/main/java/com/kingsrook/qqq/languages/javascript/QJavaScriptExecutor.java
index d4e930dc..3e100e3c 100644
--- a/qqq-language-support-javascript/src/main/java/com/kingsrook/qqq/languages/javascript/QJavaScriptExecutor.java
+++ b/qqq-language-support-javascript/src/main/java/com/kingsrook/qqq/languages/javascript/QJavaScriptExecutor.java
@@ -21,11 +21,9 @@
package com.kingsrook.qqq.languages.javascript;
+// Javax imports removed for GraalVM migration
+
-import javax.script.Bindings;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.Instant;
@@ -39,14 +37,11 @@ import com.kingsrook.qqq.backend.core.actions.scripts.logging.QCodeExecutionLogg
import com.kingsrook.qqq.backend.core.exceptions.QCodeException;
import com.kingsrook.qqq.backend.core.logging.QLogger;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
-import com.kingsrook.qqq.backend.core.utils.ExceptionUtils;
import com.kingsrook.qqq.backend.core.utils.StringUtils;
import org.apache.commons.lang.NotImplementedException;
-import org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory;
-import org.openjdk.nashorn.api.scripting.ScriptObjectMirror;
-import org.openjdk.nashorn.internal.runtime.ECMAException;
-import org.openjdk.nashorn.internal.runtime.ParserException;
-import org.openjdk.nashorn.internal.runtime.Undefined;
+import org.graalvm.polyglot.Context;
+import org.graalvm.polyglot.Source;
+import org.graalvm.polyglot.Value;
/*******************************************************************************
@@ -91,57 +86,85 @@ public class QJavaScriptExecutor implements QCodeExecutor
{
return (new BigDecimal(d));
}
- else if(object instanceof Undefined)
- {
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // well, we always said we wanted javascript to treat null & undefined the same way... here's our chance //
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
- return (null);
- }
-
- if(object instanceof ScriptObjectMirror scriptObjectMirror)
+ else if(object instanceof Value val)
{
try
{
- if("Date".equals(scriptObjectMirror.getClassName()))
+ //////////////////////////////////////////////////
+ // treat JavaScript null/undefined as Java null //
+ //////////////////////////////////////////////////
+ if(val.isNull() || val.isHostObject() && val.asHostObject() == null)
{
- ////////////////////////////////////////////////////////////////////
- // looks like the js Date is in UTC (is that because our JVM is?) //
- // so the instant being in UTC matches //
- ////////////////////////////////////////////////////////////////////
- Double millis = (Double) scriptObjectMirror.callMember("getTime");
- Instant instant = Instant.ofEpochMilli(millis.longValue());
- return (instant);
+ return null;
+ }
+ ////////////////
+ // primitives //
+ ////////////////
+ if(val.isString())
+ {
+ return val.asString();
+ }
+ if(val.isBoolean())
+ {
+ return val.asBoolean();
+ }
+ if(val.isNumber())
+ {
+ //////////////////////////////////////////
+ // preserve integer types when possible //
+ //////////////////////////////////////////
+ if(val.fitsInInt())
+ {
+ return val.asInt();
+ }
+ else if(val.fitsInLong())
+ {
+ return val.asLong();
+ }
+ else
+ {
+ return new BigDecimal(val.asDouble());
+ }
+ }
+ //////////////////////////////////////////////
+ // detect JS Date by existence of getTime() //
+ //////////////////////////////////////////////
+ if(val.hasMember("getTime") && val.canInvokeMember("getTime"))
+ {
+ double millis = val.invokeMember("getTime").asDouble();
+ return Instant.ofEpochMilli((long) millis);
+ }
+ ////////////
+ // arrays //
+ ////////////
+ if(val.hasArrayElements())
+ {
+ List