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.
*
@Component(service = ScriptEngineFactory.class)
public final class GraalJSScriptEngineFactory implements ScriptEngineFactory {
+ public static final String MIME_TYPE = "application/javascript;version=ECMAScript-2021";
+
@Override
public List<String> getScriptTypes() {
List<String> 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);
}
*
* SPDX-License-Identifier: EPL-2.0
*/
-
package org.openhab.automation.jsscripting.internal;
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;
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;
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;
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
--- /dev/null
+/**
+ * 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;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Tracks JS module dependencies
+ *
+ * @author Jonathan Gilbert - Initial contribution
+ */
+@Component(immediate = true, service = JSDependencyTracker.class)
+public class JSDependencyTracker extends DependencyTracker {
+
+ private final Logger logger = LoggerFactory.getLogger(JSDependencyTracker.class);
+
+ 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() {
+ File directory = new File(LIB_PATH);
+ if (!directory.exists()) {
+ if (!directory.mkdirs()) {
+ logger.warn("Failed to create watched directory: {}", LIB_PATH);
+ }
+ } else if (directory.isFile()) {
+ logger.warn("Trying to watch directory {}, however it is a file", LIB_PATH);
+ }
+
+ super.activate();
+ }
+
+ @Deactivate
+ public void deactivate() {
+ super.deactivate();
+ }
+}
--- /dev/null
+/**
+ * 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 <openHAB-conf>/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<String> getScriptType() {
+ assert super.getScriptType().get().equalsIgnoreCase("js");
+ return Optional.of(GraalJSScriptEngineFactory.MIME_TYPE);
+ }
+ });
+ }
+}