diff --git a/bundles/org.openhab.automation.jsscripting/pom.xml b/bundles/org.openhab.automation.jsscripting/pom.xml
index 699539f8c63..0f3f46aa70c 100644
--- a/bundles/org.openhab.automation.jsscripting/pom.xml
+++ b/bundles/org.openhab.automation.jsscripting/pom.xml
@@ -22,7 +22,7 @@
!jdk.internal.reflect.*,
!jdk.vm.ci.services
- 21.3.0
+ 22.3.0
6.2.1
${project.version}
openhab@2.0.4
@@ -50,7 +50,7 @@
frontend-maven-plugin
1.12.0
- v12.16.1
+ v16.17.1
target/js
diff --git a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/GraalJSScriptEngineFactory.java b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/GraalJSScriptEngineFactory.java
index 811b884e268..a8d4675c8a8 100644
--- a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/GraalJSScriptEngineFactory.java
+++ b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/GraalJSScriptEngineFactory.java
@@ -65,7 +65,7 @@ public final class GraalJSScriptEngineFactory implements ScriptEngineFactory {
@Override
public void scopeValues(ScriptEngine scriptEngine, Map scopeValues) {
- // noop; the are retrieved via modules, not injected
+ // noop; they are retrieved via modules, not injected
}
@Override
diff --git a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/OpenhabGraalJSScriptEngine.java b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/OpenhabGraalJSScriptEngine.java
index 66f3b4837c8..8a1282c8fd1 100644
--- a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/OpenhabGraalJSScriptEngine.java
+++ b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/OpenhabGraalJSScriptEngine.java
@@ -36,7 +36,6 @@ import java.util.function.Function;
import javax.script.ScriptContext;
import javax.script.ScriptException;
-import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Engine;
@@ -47,6 +46,7 @@ import org.openhab.automation.jsscripting.internal.fs.PrefixedSeekableByteChanne
import org.openhab.automation.jsscripting.internal.fs.ReadOnlySeekableByteArrayChannel;
import org.openhab.automation.jsscripting.internal.fs.watch.JSDependencyTracker;
import org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable;
+import org.openhab.automation.jsscripting.internal.threading.ThreadsafeTimers;
import org.openhab.core.automation.module.script.ScriptExtensionAccessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -58,6 +58,7 @@ import com.oracle.truffle.js.scriptengine.GraalJSScriptEngine;
*
* @author Jonathan Gilbert - Initial contribution
* @author Dan Cunningham - Script injections
+ * @author Florian Hotze - Create lock object for multi-thread synchronization
*/
public class OpenhabGraalJSScriptEngine
extends InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable {
@@ -68,9 +69,12 @@ public class OpenhabGraalJSScriptEngine
// final CommonJS search path for our library
private static final Path NODE_DIR = Paths.get("node_modules");
+ // shared lock object for synchronization of multi-thread access
+ private final Object lock = new Object();
+
// these fields start as null because they are populated on first use
- private @NonNullByDefault({}) String engineIdentifier;
- private @NonNullByDefault({}) Consumer scriptDependencyListener;
+ private String engineIdentifier;
+ private Consumer scriptDependencyListener;
private boolean initialized = false;
private String globalScript;
@@ -83,6 +87,8 @@ public class OpenhabGraalJSScriptEngine
super(null); // delegate depends on fields not yet initialised, so we cannot set it immediately
this.globalScript = GLOBAL_REQUIRE + (injectionCode != null ? injectionCode : "");
+ LOGGER.debug("Initializing GraalJS script engine...");
+
// Custom translate JS Objects - > Java Objects
HostAccess hostAccess = HostAccess.newBuilder(HostAccess.ALL)
// Translate JS-Joda ZonedDateTime to java.time.ZonedDateTime
@@ -194,14 +200,16 @@ public class OpenhabGraalJSScriptEngine
}
ScriptExtensionModuleProvider scriptExtensionModuleProvider = new ScriptExtensionModuleProvider(
- scriptExtensionAccessor);
+ scriptExtensionAccessor, lock);
Function, Function> wrapRequireFn = originalRequireFn -> moduleName -> scriptExtensionModuleProvider
.locatorFor(delegate.getPolyglotContext(), engineIdentifier).locateModule(moduleName)
.map(m -> (Object) m).orElseGet(() -> originalRequireFn.apply(new Object[] { moduleName }));
delegate.getBindings(ScriptContext.ENGINE_SCOPE).put(REQUIRE_WRAPPER_NAME, wrapRequireFn);
+ // Injections into the JS runtime
delegate.put("require", wrapRequireFn.apply((Function