From 1287c2be1860403feb913e393ed08486beea54da Mon Sep 17 00:00:00 2001 From: Jonathan Gilbert Date: Mon, 6 Dec 2021 13:02:45 +0000 Subject: [PATCH] GraalJS now uses automation/js Signed-off-by: Jonathan Gilbert --- .../internal/GraalJSScriptEngineFactory.java | 19 ++++-- .../internal/OpenhabGraalJSScriptEngine.java | 10 ++- .../fs/watch/JSDependencyTracker.java | 48 ++++++++++++++ .../fs/watch/JSScriptFileWatcher.java | 66 +++++++++++++++++++ 4 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSDependencyTracker.java create mode 100644 bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSScriptFileWatcher.java 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 14e9f783e8348..0c54d38fa128d 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 @@ -22,8 +22,6 @@ import org.openhab.core.automation.module.script.ScriptEngineFactory; import org.osgi.service.component.annotations.Component; -import com.oracle.truffle.js.scriptengine.GraalJSEngineFactory; - /** * An implementation of {@link ScriptEngineFactory} with customizations for GraalJS ScriptEngines. * @@ -32,13 +30,24 @@ @Component(service = ScriptEngineFactory.class) public final class GraalJSScriptEngineFactory implements ScriptEngineFactory { + public static final String MIME_TYPE = "x-application/javascript.new"; + @Override public List getScriptTypes() { List scriptTypes = new ArrayList<>(); - GraalJSEngineFactory graalJSEngineFactory = new GraalJSEngineFactory(); - scriptTypes.addAll(graalJSEngineFactory.getMimeTypes()); - scriptTypes.addAll(graalJSEngineFactory.getExtensions()); + /* + * Whilst we run in parallel with Nashorn, we use a custom mime-type to avoid + * disrupting Nashorn scripts. When Nashorn is removed, we take over the standard + * JS runtime. + */ + + // GraalJSEngineFactory graalJSEngineFactory = new GraalJSEngineFactory(); + // + // scriptTypes.addAll(graalJSEngineFactory.getMimeTypes()); + // scriptTypes.addAll(graalJSEngineFactory.getExtensions()); + + scriptTypes.add(MIME_TYPE); return Collections.unmodifiableList(scriptTypes); } 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 9f29b0d99d2c7..309ee0f5a29b5 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 @@ -15,7 +15,6 @@ import static org.openhab.core.automation.module.script.ScriptEngineFactory.*; -import java.io.File; import java.io.IOException; import java.nio.channels.SeekableByteChannel; import java.nio.file.FileSystems; @@ -33,8 +32,8 @@ import org.graalvm.polyglot.Engine; import org.openhab.automation.jsscripting.internal.fs.DelegatingFileSystem; import org.openhab.automation.jsscripting.internal.fs.PrefixedSeekableByteChannel; +import org.openhab.automation.jsscripting.internal.fs.watch.JSDependencyTracker; import org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocable; -import org.openhab.core.OpenHAB; import org.openhab.core.automation.module.script.ScriptExtensionAccessor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,8 +50,6 @@ public class OpenhabGraalJSScriptEngine extends InvocationInterceptingScriptEngi private static final Logger LOGGER = LoggerFactory.getLogger(OpenhabGraalJSScriptEngine.class); private static final String REQUIRE_WRAPPER_NAME = "__wraprequire__"; - private static final String MODULE_DIR = String.join(File.separator, OpenHAB.getConfigFolder(), "automation", "lib", - "javascript", "personal"); // these fields start as null because they are populated on first use private @NonNullByDefault({}) String engineIdentifier; @@ -70,8 +67,9 @@ public OpenhabGraalJSScriptEngine() { Engine.newBuilder().allowExperimentalOptions(true).option("engine.WarnInterpreterOnly", "false") .build(), Context.newBuilder("js").allowExperimentalOptions(true).allowAllAccess(true) - .option("js.commonjs-require-cwd", MODULE_DIR).option("js.nashorn-compat", "true") // to ease - // migration + .option("js.commonjs-require-cwd", JSDependencyTracker.LIB_PATH) + .option("js.nashorn-compat", "true") // to ease + // migration .option("js.ecmascript-version", "2021") // nashorn compat will enforce es5 compatibility, we // want ecma2021 .option("js.commonjs-require", "true") // enable CommonJS module support diff --git a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSDependencyTracker.java b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSDependencyTracker.java new file mode 100644 index 0000000000000..a92114f4b455c --- /dev/null +++ b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSDependencyTracker.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.openhab.automation.jsscripting.internal.fs.watch; + +import java.io.File; + +import org.openhab.core.OpenHAB; +import org.openhab.core.automation.module.script.rulesupport.loader.DependencyTracker; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Deactivate; + +/** + * Tracks JS module dependencies + * + * @author Jonathan Gilbert - Initial contribution + */ +@Component(immediate = true, service = JSDependencyTracker.class) +public class JSDependencyTracker extends DependencyTracker { + + public static final String LIB_PATH = String.join(File.separator, OpenHAB.getConfigFolder(), "automation", "js", + "node_modules"); + + public JSDependencyTracker() { + super(LIB_PATH); + } + + @Activate + public void activate() { + super.activate(); + } + + @Deactivate + public void deactivate() { + super.deactivate(); + } +} diff --git a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSScriptFileWatcher.java b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSScriptFileWatcher.java new file mode 100644 index 0000000000000..229d9eafa00dc --- /dev/null +++ b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/fs/watch/JSScriptFileWatcher.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.openhab.automation.jsscripting.internal.fs.watch; + +import java.io.File; +import java.util.Optional; + +import org.openhab.automation.jsscripting.internal.GraalJSScriptEngineFactory; +import org.openhab.core.automation.module.script.ScriptEngineManager; +import org.openhab.core.automation.module.script.rulesupport.loader.ScriptFileReference; +import org.openhab.core.automation.module.script.rulesupport.loader.ScriptFileWatcher; +import org.openhab.core.service.ReadyService; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Deactivate; +import org.osgi.service.component.annotations.Reference; + +/** + * Monitors /automation/js for Javascript files + * + * @author Jonathan Gilbert - Initial contribution + */ +@Component(immediate = true) +public class JSScriptFileWatcher extends ScriptFileWatcher { + private static final String FILE_DIRECTORY = "automation" + File.separator + "js"; + + @Activate + public JSScriptFileWatcher(final @Reference ScriptEngineManager manager, final @Reference ReadyService readyService, + final @Reference JSDependencyTracker jsDependencyTracker) { + super(manager, jsDependencyTracker, readyService, FILE_DIRECTORY); + } + + @Activate + @Override + public void activate() { + super.activate(); + } + + @Deactivate + @Override + public void deactivate() { + super.deactivate(); + } + + @Override + protected boolean createAndLoad(ScriptFileReference ref) { + return super.createAndLoad(new ScriptFileReference(ref.getScriptFileURL()) { + @Override + public Optional getScriptType() { + assert super.getScriptType().get().equalsIgnoreCase("js"); + return Optional.of(GraalJSScriptEngineFactory.MIME_TYPE); + } + }); + } +}