forked from openhab/openhab-addons
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[jsscripting] ES6+ Support (openhab#8516)
Signed-off-by: Jonathan Gilbert <jpg@trillica.com>
- Loading branch information
Showing
21 changed files
with
1,345 additions
and
0 deletions.
There are no files selected for viewing
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
This content is produced and maintained by the openHAB project. | ||
|
||
* Project home: https://www.openhab.org | ||
|
||
== Declared Project Licenses | ||
|
||
This program and the accompanying materials are made available under the terms | ||
of the Eclipse Public License 2.0 which is available at | ||
https://www.eclipse.org/legal/epl-2.0/. | ||
|
||
== Source Code | ||
|
||
https://github.com/openhab/openhab-addons |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# JavaScript Scripting | ||
|
||
This add-on provides support for JavaScript (ECMAScript 2021+) that can be used as a scripting language within automation rules. | ||
|
||
## Creating JavaScript Scripts | ||
|
||
When this add-on is installed, JavaScript script actions will be run by this add-on and allow ECMAScript 2021+ features. | ||
|
||
Alternatively, you can create scripts in the `automation/jsr223` configuration directory. | ||
If you create an empty file called `test.js`, you will see a log line with information similar to: | ||
|
||
```text | ||
... [INFO ] [.a.m.s.r.i.l.ScriptFileWatcher:150 ] - Loading script 'test.js' | ||
``` | ||
|
||
To enable debug logging, use the [console logging]({{base}}/administration/logging.html) commands to enable debug logging for the automation functionality: | ||
|
||
```text | ||
log:set DEBUG org.openhab.core.automation | ||
``` | ||
|
||
For more information on the available APIs in scripts see the [JSR223 Scripting]({{base}}/configuration/jsr223.html) documentation. | ||
|
||
## Script Examples | ||
|
||
JavaScript scripts provide access to almost all the functionality in an openHAB runtime environment. | ||
As a simple example, the following script logs "Hello, World!". | ||
Note that `console.log` will usually not work since the output has no terminal to display the text. | ||
The openHAB server uses the [SLF4J](https://www.slf4j.org/) library for logging. | ||
|
||
```js | ||
const LoggerFactory = Java.type('org.slf4j.LoggerFactory'); | ||
|
||
LoggerFactory.getLogger("org.openhab.core.automation.examples").info("Hello world!"); | ||
``` | ||
|
||
Depending on the openHAB logging configuration, you may need to prefix logger names with `org.openhab.core.automation` for them to show up in the log file (or you modify the logging configuration). | ||
|
||
The script uses the [LoggerFactory](https://www.slf4j.org/apidocs/org/slf4j/Logger.html) to obtain a named logger and then logs a message like: | ||
|
||
```text | ||
... [INFO ] [.openhab.core.automation.examples:-2 ] - Hello world! | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Bundle-SymbolicName: ${project.artifactId} | ||
DynamicImport-Package: * | ||
Import-Package: org.openhab.core.automation.module.script,javax.management,javax.script,javax.xml.datatype,javax.xml.stream;version="[1.0,2)",org.osgi.framework;version="[1.8,2)",org.slf4j;version="[1.7,2)" | ||
Require-Capability: osgi.extender; | ||
filter:="(osgi.extender=osgi.serviceloader.processor)", | ||
osgi.serviceloader; | ||
filter:="(osgi.serviceloader=org.graalvm.polyglot.impl.AbstractPolyglotImpl)"; | ||
cardinality:=multiple | ||
|
||
SPI-Provider: * | ||
SPI-Consumer: * | ||
|
||
-fixupmessages "Classes found in the wrong directory"; restrict:=error; is:=warning |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
|
||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
|
||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>org.openhab.addons.bundles</groupId> | ||
<artifactId>org.openhab.addons.reactor.bundles</artifactId> | ||
<version>3.1.0-SNAPSHOT</version> | ||
</parent> | ||
|
||
<artifactId>org.openhab.automation.jsscripting</artifactId> | ||
|
||
<name>openHAB Add-ons :: Bundles :: Automation :: JSScripting</name> | ||
|
||
<properties> | ||
<bnd.importpackage> | ||
!sun.misc.*, | ||
!sun.reflect.*, | ||
!com.sun.management.*, | ||
!jdk.internal.reflect.*, | ||
!jdk.vm.ci.services | ||
</bnd.importpackage> | ||
<graal.version>20.1.0</graal.version> | ||
<asm.version>6.2.1</asm.version> | ||
<oh.version>${project.version}</oh.version> | ||
</properties> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-dependency-plugin</artifactId> | ||
<executions> | ||
<execution> | ||
<id>embed-dependencies</id> | ||
<goals> | ||
<goal>unpack-dependencies</goal> | ||
</goals> | ||
<configuration> | ||
<excludes>META-INF/services/com.oracle.truffle.api.TruffleLanguage$Provider</excludes> <!-- we'll provide this --> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.graalvm.truffle</groupId> | ||
<artifactId>truffle-api</artifactId> | ||
<version>${graal.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.graalvm.js</groupId> | ||
<artifactId>js-scriptengine</artifactId> | ||
<version>${graal.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.graalvm.js</groupId> | ||
<artifactId>js-launcher</artifactId> | ||
<version>${graal.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.graalvm.sdk</groupId> | ||
<artifactId>graal-sdk</artifactId> | ||
<version>${graal.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.graalvm.regex</groupId> | ||
<artifactId>regex</artifactId> | ||
<version>${graal.version}</version> | ||
</dependency> | ||
<dependency> <!-- this must come AFTER the regex lib --> | ||
<groupId>org.graalvm.js</groupId> | ||
<artifactId>js</artifactId> | ||
<version>${graal.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.ibm.icu</groupId> | ||
<artifactId>icu4j</artifactId> | ||
<version>62.1</version> | ||
</dependency> | ||
|
||
<!-- include as version required is older than OH provides --> | ||
<dependency> | ||
<groupId>org.ow2.asm</groupId> | ||
<artifactId>asm</artifactId> | ||
<version>${asm.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.ow2.asm</groupId> | ||
<artifactId>asm-commons</artifactId> | ||
<version>${asm.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.ow2.asm</groupId> | ||
<artifactId>asm-tree</artifactId> | ||
<version>${asm.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.ow2.asm</groupId> | ||
<artifactId>asm-util</artifactId> | ||
<version>${asm.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.ow2.asm</groupId> | ||
<artifactId>asm-analysis</artifactId> | ||
<version>${asm.version}</version> | ||
</dependency> | ||
</dependencies> | ||
</project> |
10 changes: 10 additions & 0 deletions
10
bundles/org.openhab.automation.jsscripting/src/main/feature/feature.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
|
||
<features name="org.openhab.automation.jsscripting-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0"> | ||
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository> | ||
|
||
<feature name="openhab-automation-jsscripting" description="JSScripting" version="${project.version}"> | ||
<feature>openhab-runtime-base</feature> | ||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.automation.jsscripting/${project.version}</bundle> | ||
</feature> | ||
</features> |
37 changes: 37 additions & 0 deletions
37
...utomation.jsscripting/src/main/java/org/openhab/automation/jsscripting/ClassExtender.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/** | ||
* 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; | ||
|
||
import com.oracle.truffle.js.runtime.java.adapter.JavaAdapterFactory; | ||
|
||
/** | ||
* Class utility to allow creation of 'extendable' classes with a classloader of the GraalJS bundle, rather than the | ||
* classloader of the file being extended. | ||
* | ||
* @author Jonathan Gilbert - Initial contribution | ||
*/ | ||
public class ClassExtender { | ||
private static ClassLoader classLoader = ClassExtender.class.getClassLoader(); | ||
|
||
public static Object extend(String className) { | ||
try { | ||
return extend(Class.forName(className)); | ||
} catch (ClassNotFoundException e) { | ||
throw new RuntimeException("Cannot find class " + className, e); | ||
} | ||
} | ||
|
||
public static Object extend(Class<?> clazz) { | ||
return JavaAdapterFactory.getAdapterClassFor(clazz, null, classLoader); | ||
} | ||
} |
49 changes: 49 additions & 0 deletions
49
...src/main/java/org/openhab/automation/jsscripting/internal/DebuggingGraalScriptEngine.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/** | ||
* 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; | ||
|
||
import javax.script.Invocable; | ||
import javax.script.ScriptEngine; | ||
import javax.script.ScriptException; | ||
|
||
import org.eclipse.jdt.annotation.NonNullByDefault; | ||
import org.graalvm.polyglot.PolyglotException; | ||
import org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocable; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
/** | ||
* Wraps ScriptEngines provided by Graal to provide error messages and stack traces for scripts. | ||
* | ||
* @author Jonathan Gilbert - Initial contribution | ||
*/ | ||
@NonNullByDefault | ||
class DebuggingGraalScriptEngine<T extends ScriptEngine & Invocable> | ||
extends InvocationInterceptingScriptEngineWithInvocable<T> { | ||
|
||
private static final Logger stackLogger = LoggerFactory.getLogger("org.openhab.automation.script.javascript.stack"); | ||
|
||
public DebuggingGraalScriptEngine(T delegate) { | ||
super(delegate); | ||
} | ||
|
||
@Override | ||
public ScriptException afterThrowsInvocation(ScriptException se) { | ||
Throwable cause = se.getCause(); | ||
if (cause instanceof PolyglotException) { | ||
stackLogger.error("Failed to execute script:", cause); | ||
} | ||
return se; | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
...src/main/java/org/openhab/automation/jsscripting/internal/GraalJSScriptEngineFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/** | ||
* 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; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import javax.script.ScriptEngine; | ||
|
||
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. | ||
* | ||
* @author Jonathan Gilbert - Initial contribution | ||
*/ | ||
@Component(service = ScriptEngineFactory.class) | ||
public final class GraalJSScriptEngineFactory implements ScriptEngineFactory { | ||
|
||
@Override | ||
public List<String> getScriptTypes() { | ||
List<String> scriptTypes = new ArrayList<>(); | ||
GraalJSEngineFactory graalJSEngineFactory = new GraalJSEngineFactory(); | ||
|
||
scriptTypes.addAll(graalJSEngineFactory.getMimeTypes()); | ||
scriptTypes.addAll(graalJSEngineFactory.getExtensions()); | ||
|
||
return Collections.unmodifiableList(scriptTypes); | ||
} | ||
|
||
@Override | ||
public void scopeValues(ScriptEngine scriptEngine, Map<String, Object> scopeValues) { | ||
// noop; the are retrieved via modules, not injected | ||
} | ||
|
||
@Override | ||
public ScriptEngine createScriptEngine(String scriptType) { | ||
OpenhabGraalJSScriptEngine engine = new OpenhabGraalJSScriptEngine(); | ||
return new DebuggingGraalScriptEngine<>(engine); | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
....jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/ModuleLocator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/** | ||
* 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; | ||
|
||
import java.util.Optional; | ||
|
||
import org.graalvm.polyglot.Value; | ||
|
||
/** | ||
* Locates modules from a module name | ||
* | ||
* @author Jonathan Gilbert - Initial contribution | ||
*/ | ||
public interface ModuleLocator { | ||
Optional<Value> locateModule(String name); | ||
} |
Oops, something went wrong.