Skip to content

Commit dc51ff6

Browse files
committed
[demo] use QuickJs for the JavaScript provider
1 parent 6bc6896 commit dc51ff6

File tree

4 files changed

+82
-39
lines changed

4 files changed

+82
-39
lines changed

pom.xml

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
<qosdk.version>6.6.8</qosdk.version>
2525
<assertj.version>3.27.1</assertj.version>
2626
<spotless.version>2.43.0</spotless.version>
27+
<chicory.version>1.0.0</chicory.version>
2728
</properties>
2829

2930
<dependencyManagement>
@@ -42,6 +43,13 @@
4243
<type>pom</type>
4344
<scope>import</scope>
4445
</dependency>
46+
<dependency>
47+
<groupId>com.dylibso.chicory</groupId>
48+
<artifactId>bom</artifactId>
49+
<version>${chicory.version}</version>
50+
<type>pom</type>
51+
<scope>import</scope>
52+
</dependency>
4553
</dependencies>
4654
</dependencyManagement>
4755

@@ -73,6 +81,14 @@
7381
<artifactId>generator-annotations</artifactId>
7482
<version>${fabric8-client.version}</version>
7583
</dependency>
84+
<dependency>
85+
<groupId>com.dylibso.chicory</groupId>
86+
<artifactId>runtime</artifactId>
87+
</dependency>
88+
<dependency>
89+
<groupId>com.dylibso.chicory</groupId>
90+
<artifactId>wasi</artifactId>
91+
</dependency>
7692
<dependency>
7793
<groupId>org.awaitility</groupId>
7894
<artifactId>awaitility</artifactId>
@@ -88,23 +104,6 @@
88104
<groupId>io.quarkus</groupId>
89105
<artifactId>quarkus-container-image-jib</artifactId>
90106
</dependency>
91-
<dependency>
92-
<groupId>org.graalvm.polyglot</groupId>
93-
<artifactId>polyglot</artifactId>
94-
<version>${graalvm.version}</version>
95-
</dependency>
96-
<dependency>
97-
<groupId>org.graalvm.js</groupId>
98-
<artifactId>js-scriptengine</artifactId>
99-
<version>${graalvm.version}</version>
100-
</dependency>
101-
<dependency>
102-
<groupId>org.graalvm.polyglot</groupId>
103-
<artifactId>js-community</artifactId>
104-
<version>${graalvm.version}</version>
105-
<type>pom</type>
106-
<scope>runtime</scope>
107-
</dependency>
108107
<dependency>
109108
<groupId>org.bouncycastle</groupId>
110109
<artifactId>bcpkix-jdk18on</artifactId>
@@ -207,6 +206,23 @@
207206
</executions>
208207
</plugin>
209208

209+
<plugin>
210+
<groupId>com.dylibso.chicory</groupId>
211+
<artifactId>aot-maven-plugin-experimental</artifactId>
212+
<version>${chicory.version}</version>
213+
<executions>
214+
<execution>
215+
<id>quickJs</id>
216+
<goals>
217+
<goal>wasm-aot-gen</goal>
218+
</goals>
219+
<configuration>
220+
<name>io.javaoperatorsdk.operator.glue.wasm.QuickJs</name>
221+
<wasmFile>src/main/resources/wasm/quickjs-provider.wasm</wasmFile>
222+
</configuration>
223+
</execution>
224+
</executions>
225+
</plugin>
210226
</plugins>
211227
</build>
212228

src/main/java/io/javaoperatorsdk/operator/glue/conditions/JavaScripCondition.java

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package io.javaoperatorsdk.operator.glue.conditions;
22

3+
import java.io.ByteArrayOutputStream;
4+
import java.io.IOException;
35
import java.time.LocalDateTime;
46
import java.time.temporal.ChronoUnit;
57
import java.util.Map;
68
import java.util.stream.Collectors;
79

8-
import javax.script.*;
9-
1010
import org.slf4j.Logger;
1111
import org.slf4j.LoggerFactory;
1212

@@ -17,14 +17,20 @@
1717
import io.javaoperatorsdk.operator.glue.GlueException;
1818
import io.javaoperatorsdk.operator.glue.Utils;
1919
import io.javaoperatorsdk.operator.glue.customresource.glue.Glue;
20+
import io.javaoperatorsdk.operator.glue.wasm.QuickJsModule;
2021
import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
2122

23+
import com.dylibso.chicory.runtime.ImportValues;
24+
import com.dylibso.chicory.runtime.Instance;
25+
import com.dylibso.chicory.wasi.WasiOptions;
26+
import com.dylibso.chicory.wasi.WasiPreview1;
27+
28+
import static java.nio.charset.StandardCharsets.UTF_8;
29+
2230
public class JavaScripCondition implements Condition<GenericKubernetesResource, Glue> {
2331

2432
private static final Logger LOG = LoggerFactory.getLogger(JavaScripCondition.class);
2533

26-
private static final String RESOURCE_AS_STRING_NAME_SUFFIX = "Str";
27-
2834
private final String inputScript;
2935

3036
public JavaScripCondition(String inputScript) {
@@ -35,50 +41,71 @@ public JavaScripCondition(String inputScript) {
3541
public boolean isMet(DependentResource<GenericKubernetesResource, Glue> dependentResource,
3642
Glue glue,
3743
Context<Glue> context) {
38-
try {
44+
try (var jsStderr = new ByteArrayOutputStream();
45+
var wasi = WasiPreview1.builder()
46+
.withOptions(WasiOptions.builder().withStderr(jsStderr).build()).build()) {
3947
var start = LocalDateTime.now();
40-
ScriptEngineManager manager = new ScriptEngineManager();
41-
ScriptEngine engine = manager.getEngineByName("js");
48+
49+
var quickjs = Instance.builder(QuickJsModule.load())
50+
.withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build())
51+
.withMachineFactory(QuickJsModule::create)
52+
.build();
4253

4354
StringBuilder finalScript = new StringBuilder();
44-
addTargetResourceToScript(dependentResource, glue, context, engine, finalScript);
45-
addSecondaryResourceToScript(glue, context, engine, finalScript);
55+
addTargetResourceToScript(dependentResource, glue, context, finalScript);
56+
addSecondaryResourceToScript(glue, context, finalScript);
4657

4758
finalScript.append("\n").append(inputScript);
4859

49-
LOG.debug("Final Condition JS:\n{}", finalScript);
60+
// Using stderr to return the result
61+
String finalJsCode = "console.error(eval(`" + finalScript + "`));";
62+
LOG.debug("Final Condition JS:\n{}", finalJsCode);
63+
byte[] jsCode = finalJsCode.getBytes(UTF_8);
64+
65+
var ptr =
66+
quickjs.export("canonical_abi_realloc")
67+
.apply(
68+
0, // original_ptr
69+
0, // original_size
70+
1, // alignment
71+
jsCode.length // new size
72+
)[0];
73+
74+
quickjs.memory().write((int) ptr, jsCode);
75+
var aggregatedCodePtr = quickjs.export("compile_src").apply(ptr, jsCode.length)[0];
76+
77+
var codePtr = quickjs.memory().readI32((int) aggregatedCodePtr); // 32 bit
78+
var codeLength = quickjs.memory().readU32((int) aggregatedCodePtr + 4);
79+
80+
quickjs.export("eval_bytecode").apply(codePtr, codeLength);
5081

51-
CompiledScript script = ((Compilable) engine).compile(finalScript.toString());
52-
var res = (boolean) script.eval();
82+
var res = Boolean.valueOf(jsStderr.toString().trim());
5383
LOG.debug("JS Condition evaluated as: {} within {}ms", res,
5484
ChronoUnit.MILLIS.between(start, LocalDateTime.now()));
5585
return res;
56-
} catch (ScriptException e) {
86+
} catch (IOException e) {
5787
throw new GlueException(e);
5888
}
5989
}
6090

6191
private static void addSecondaryResourceToScript(Glue glue,
6292
Context<Glue> context,
63-
ScriptEngine engine, StringBuilder finalScript) {
93+
StringBuilder finalScript) {
6494
Map<String, String> namedSecondaryResources =
6595
nameAndSerializeSecondaryResources(context, glue);
6696
namedSecondaryResources.forEach((k, v) -> {
67-
var stringKey = k + RESOURCE_AS_STRING_NAME_SUFFIX;
68-
engine.put(stringKey, v);
69-
finalScript.append("const ").append(k).append(" = JSON.parse(").append(stringKey)
70-
.append(");\n");
97+
finalScript.append("const ").append(k).append(" = JSON.parse('").append(v)
98+
.append("');\n");
7199
});
72100
}
73101

74102
private static void addTargetResourceToScript(
75103
DependentResource<GenericKubernetesResource, Glue> dependentResource,
76104
Glue glue,
77-
Context<Glue> context, ScriptEngine engine, StringBuilder finalScript) {
105+
Context<Glue> context, StringBuilder finalScript) {
78106
var target = dependentResource.getSecondaryResource(glue, context);
79107
target.ifPresent(t -> {
80-
engine.put("targetStr", Serialization.asJson(t));
81-
finalScript.append("const target = JSON.parse(targetStr);\n");
108+
finalScript.append("const target = JSON.parse('" + Serialization.asJson(t) + "');\n");
82109
});
83110
}
84111

1.7 MB
Binary file not shown.

src/test/java/io/javaoperatorsdk/operator/glue/JavaScripConditionTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ void setup() {
4040
void javaScriptSimpleConditionTest() {
4141

4242
var condition = new JavaScripCondition("""
43-
x = 1;
43+
const x = 1;
4444
x<2;
4545
""");
4646

0 commit comments

Comments
 (0)