Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PoC for JSR223 script-engine #314

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
<module>wasi</module>
<module>wasm-corpus</module>
<module>cli</module>
<module>scriptengine</module>
</modules>

<scm>
Expand Down
31 changes: 31 additions & 0 deletions scriptengine/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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>com.dylibso.chicory</groupId>
<artifactId>chicory</artifactId>
<version>999-SNAPSHOT</version>
</parent>
<artifactId>scriptengine</artifactId>
<name>Chicory - JSR 223 Script Engine</name>
<description>WebAssembly Script Engine</description>
<dependencies>
<dependency>
<groupId>com.dylibso.chicory</groupId>
<artifactId>runtime</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
</dependency>

<dependency>
<!-- generates meta-inf services file for script engine -->
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package com.dylibso.chicory.scriptengine;

import com.dylibso.chicory.runtime.Module;
import com.dylibso.chicory.wasm.types.Value;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Base64;
import java.util.Objects;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;
import javax.script.SimpleBindings;

public class ChicoryScriptEngine implements ScriptEngine {

@Override
public Object eval(String script, ScriptContext context) throws ScriptException {
return null;
}

@Override
public Object eval(Reader reader, ScriptContext context) throws ScriptException {
return null;
}

@Override
public Object eval(String script) throws ScriptException {
return eval(script, (ScriptContext) null);
}

@Override
public Object eval(Reader reader) throws ScriptException {
return eval(reader, (ScriptContext) null);
}

@Override
public Object eval(String script, Bindings bindings) throws ScriptException {
return eval(new StringReader(script), bindings);
}

@Override
public Object eval(Reader reader, Bindings bindings) throws ScriptException {

StringWriter sw = new StringWriter();
try {
reader.transferTo(sw);
} catch (IOException e) {
throw new RuntimeException(e);
}

byte[] wasmBytes =
Base64.getDecoder().decode(Objects.requireNonNull(sw.toString(), "script"));

int arg0 = ((Integer) bindings.get("arg0")).intValue();
String func = (String) bindings.get("func");

var module = Module.builder(wasmBytes).build();
var instance = module.instantiate();
var iterFact = instance.export(func);
var result = iterFact.apply(Value.i32(arg0))[0].asInt();

return result;
}

@Override
public void put(String key, Object value) {}

@Override
public Object get(String key) {
return null;
}

@Override
public Bindings getBindings(int scope) {
return null;
}

@Override
public void setBindings(Bindings bindings, int scope) {}

@Override
public Bindings createBindings() {
return new SimpleBindings();
}

@Override
public ScriptContext getContext() {
return null;
}

@Override
public void setContext(ScriptContext context) {}

@Override
public ScriptEngineFactory getFactory() {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.dylibso.chicory.scriptengine;

import com.google.auto.service.AutoService;
import java.util.List;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;

@AutoService(ScriptEngineFactory.class)
public class ChicoryScriptEngineFactory implements ScriptEngineFactory {

@Override
public String getEngineName() {
return "Chicory ScriptEngine";
}

@Override
public String getEngineVersion() {
return getClass().getPackage().getImplementationVersion();
}

@Override
public List<String> getExtensions() {
return List.of("wasm");
}

@Override
public List<String> getMimeTypes() {
return List.of("application/wasm");
}

@Override
public List<String> getNames() {
return List.of("chicory");
}

@Override
public String getLanguageName() {
return "WebAssembly";
}

@Override
public String getLanguageVersion() {
return "1.0";
}

@Override
public Object getParameter(String key) {
return null;
}

@Override
public String getMethodCallSyntax(String obj, String m, String... args) {
return "";
}

@Override
public String getOutputStatement(String toDisplay) {
return "";
}

@Override
public String getProgram(String... statements) {
return "";
}

@Override
public ScriptEngine getScriptEngine() {
return new ChicoryScriptEngine();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.dylibso.chicory.scriptengine;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class ChicoryScriptEngineTest {

ScriptEngineManager engines;

@BeforeEach
public void init() {
engines = new ScriptEngineManager();
}

@Test
public void scriptEngineLookupByName() {
Assertions.assertNotNull(engines.getEngineByName("chicory"));
}

@Test
public void scriptEngineLookupByExtension() {
Assertions.assertNotNull(engines.getEngineByExtension("wasm"));
}

@Test
public void simpleEval() throws Exception {
ScriptEngine engine = engines.getEngineByExtension("wasm");
byte[] wasmBytes =
Files.readAllBytes(
Path.of("../wasm-corpus/src/test/resources/compiled/iterfact.wat.wasm"));
String wasmBase64 = Base64.getEncoder().encodeToString(wasmBytes);
Bindings bindings = engine.createBindings();
bindings.put("arg0", 5);
bindings.put("func", "iterFact");
Object result = engine.eval(wasmBase64, bindings);
Assertions.assertEquals(120, result);
}
}