Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ public class DoubleViewRendererConfiguration {
*/
private boolean useOptimization = true;

/**
* Enable development mode.
* In development mode, the renderer loads the code each time before rendering. Which allows to see the changes without restarting the application.
*/
private boolean devMode = false;

public String getClientBundleURL() {
return clientBundleURL;
}
Expand Down Expand Up @@ -96,4 +102,17 @@ public String getHtmlTemplatePath() {
public void setHtmlTemplatePath(String htmlTemplatePath) {
this.htmlTemplatePath = htmlTemplatePath;
}

public boolean isDevMode() {
return devMode;
}

public void setDevMode(boolean devMode) {
this.devMode = devMode;
}

public void setDevMode() {
setDevMode(true);
}

}
73 changes: 59 additions & 14 deletions doubleview/src/main/java/io/emeraldpay/doubleview/JSContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,17 @@ public Value getComponents() {
return components;
}

public static class Builder {
private final Source bundle;
private final Source render;
private final Context.Builder polyglotContext;
public static Builder builder(DoubleViewRendererConfiguration configuration) throws IOException {
if (configuration.isDevMode()) {
return new DevBuilder(configuration);
}
return new DefaultBuilder(configuration);
}

public static abstract class Builder {
protected final Context.Builder polyglotContext;

Builder(DoubleViewRendererConfiguration configuration) throws IOException {
public Builder(DoubleViewRendererConfiguration configuration) {
Engine.Builder engine = Engine.newBuilder("js")
.out(System.out)
.err(System.err);
Expand All @@ -72,17 +77,20 @@ public static class Builder {
engine = engine.option("engine.WarnInterpreterOnly", "false");
}

bundle = loadSource(configuration.getServerBundlePath());
render = loadSource(configuration.getRendererScript());

polyglotContext = Context.newBuilder("js")
.engine(engine.build())
.allowAllAccess(true)
.option("js.esm-eval-returns-exports", "true")
.option("js.unhandled-rejections", "throw");
}

public Source loadSource(String path) throws IOException {
/**
* Creates a fresh state for execution. Should be called each time the code is executed.
* @return a new JSContext
*/
abstract JSContext build();

public static Source loadSource(String path) throws IOException {
if (path.startsWith(".") || path.startsWith("/")) {
path = "file:" + path;
}
Expand All @@ -93,7 +101,7 @@ public Source loadSource(String path) throws IOException {
if (path.startsWith("classpath:")) {
String resourcePath = path.substring("classpath:".length());
fileName = resourcePath.substring(resourcePath.lastIndexOf('/') + 1);
try (var stream = getClass().getResourceAsStream(resourcePath)) {
try (var stream = Builder.class.getResourceAsStream(resourcePath)) {
if (stream == null) {
throw new IllegalArgumentException("Resource not found: " + resourcePath);
}
Expand All @@ -111,14 +119,51 @@ public Source loadSource(String path) throws IOException {
.mimeType("application/javascript+module")
.build();
}
}

public static class DefaultBuilder extends Builder {
private final Source bundle;
private final Source render;

private DefaultBuilder(DoubleViewRendererConfiguration configuration) throws IOException {
super(configuration);
bundle = loadSource(configuration.getServerBundlePath());
render = loadSource(configuration.getRendererScript());

}

/**
* Creates a fresh state for execution. Should be called each time the code is executed.
* @return a new JSContext
*/
public JSContext build() {
return new JSContext(polyglotContext.build(), bundle, render);
}

}

/**
* In development mode, the renderer loads the code each time before rendering.
* Which allows to see the changes without restarting the application.
*/
public static class DevBuilder extends Builder {
private final String serverBundlePath;
private final String rendererScript;

private DevBuilder(DoubleViewRendererConfiguration configuration) {
super(configuration);
serverBundlePath = configuration.getServerBundlePath();
rendererScript = configuration.getRendererScript();
}

public JSContext build() {
Source bundle;
Source render;
try {
bundle = loadSource(serverBundlePath);
render = loadSource(rendererScript);
} catch (IOException e) {
throw new RuntimeException("Server bundle or render script load failed in dev mode", e);
}
return new JSContext(polyglotContext.build(), bundle, render);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class JSContextProvider {
public JSContextProvider(DoubleViewRendererConfiguration configuration) {
context = ThreadLocal.withInitial(() -> {
try {
return new JSContext.Builder(configuration);
return JSContext.builder(configuration);
} catch (Exception e) {
throw new RuntimeException("Failed to create JSContext", e);
}
Expand Down
Loading