Skip to content

Commit

Permalink
[jsscripting] Cache @jsscripting-globals.js across all engines
Browse files Browse the repository at this point in the history
Signed-off-by: Florian Hotze <florianh_dev@icloud.com>
  • Loading branch information
florian-h05 committed Dec 30, 2022
1 parent ba5fb0e commit e4c9547
Showing 1 changed file with 32 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.AccessMode;
import java.nio.file.FileSystems;
Expand All @@ -42,6 +44,7 @@
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Engine;
import org.graalvm.polyglot.HostAccess;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Value;
import org.openhab.automation.jsscripting.internal.fs.DelegatingFileSystem;
import org.openhab.automation.jsscripting.internal.fs.PrefixedSeekableByteChannel;
Expand All @@ -67,7 +70,17 @@ public class OpenhabGraalJSScriptEngine
extends InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable<GraalJSScriptEngine> {

private static final Logger LOGGER = LoggerFactory.getLogger(OpenhabGraalJSScriptEngine.class);
private static final String GLOBAL_REQUIRE = "require(\"@jsscripting-globals\");";
private static Source GLOBAL_SOURCE;

static {
try {
GLOBAL_SOURCE = Source.newBuilder("js", getFileAsReader("node_modules/@jsscripting-globals.js"),
"@jsscripting-globals.js").cached(true).build();
} catch (IOException e) {
LOGGER.error("Failed to load global script", e);
}
}

private static final String REQUIRE_WRAPPER_NAME = "__wraprequire__";
/** Final CommonJS search path for our library */
private static final Path NODE_DIR = Paths.get("node_modules");
Expand Down Expand Up @@ -98,15 +111,15 @@ public class OpenhabGraalJSScriptEngine
private @Nullable Consumer<String> scriptDependencyListener;

private boolean initialized = false;
private final String globalScript;
private final String injectionCode;

/**
* Creates an implementation of ScriptEngine (& Invocable), wrapping the contained engine, that tracks the script
* lifecycle and provides hooks for scripts to do so too.
*/
public OpenhabGraalJSScriptEngine(@Nullable String injectionCode, JSScriptServiceUtil jsScriptServiceUtil) {
super(null); // delegate depends on fields not yet initialised, so we cannot set it immediately
this.globalScript = GLOBAL_REQUIRE + (injectionCode != null ? injectionCode : "");
this.injectionCode = (injectionCode != null ? injectionCode : "");
this.jsRuntimeFeatures = jsScriptServiceUtil.getJSRuntimeFeatures(lock);

LOGGER.debug("Initializing GraalJS script engine...");
Expand Down Expand Up @@ -230,7 +243,8 @@ protected void beforeInvocation() {

try {
LOGGER.debug("Evaluating global script...");
eval(globalScript);
delegate.getPolyglotContext().eval(GLOBAL_SOURCE);
eval(injectionCode);
LOGGER.debug("Successfully initialized GraalJS script engine.");
} catch (ScriptException e) {
LOGGER.error("Could not inject global script", e);
Expand Down Expand Up @@ -274,4 +288,18 @@ private boolean isRootNodePath(Path path) {
private String nodeFileToResource(Path path) {
return "/" + path.subpath(0, path.getNameCount()).toString().replace('\\', '/');
}

/**
* @param fileName filename relative to the resources folder
* @return file as {@link InputStreamReader}
*/
private static Reader getFileAsReader(String fileName) {
InputStream ioStream = OpenhabGraalJSScriptEngine.class.getClassLoader().getResourceAsStream(fileName);

if (ioStream == null) {
throw new IllegalArgumentException(fileName + " not found");
}

return new InputStreamReader(ioStream);
}
}

0 comments on commit e4c9547

Please sign in to comment.