Skip to content

Commit

Permalink
DRAFT: working language server connection
Browse files Browse the repository at this point in the history
  • Loading branch information
4e6 committed Apr 11, 2024
1 parent 27df630 commit f1da6ec
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 9 deletions.
2 changes: 1 addition & 1 deletion app/gui2/ydoc-server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ declare global {

const wss = new WebSocketServer({ host: 'localhost', port: 1234 })

wss.onconnect = (socket, url) => setupGatewayClient(socket, "ws://localhost:8080", url)
wss.onconnect = (socket, url) => setupGatewayClient(socket, "ws://127.0.0.1:30616", 'index')

wss.start()
5 changes: 4 additions & 1 deletion app/gui2/ydoc-server/ydoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,12 @@ class YjsConnection extends ObservableV2<{ close(): void }> {
}

send(message: Uint8Array) {
if (this.ws.readyState !== WebSocket.CONNECTING && this.ws.readyState !== WebSocket.OPEN) {
if (this.ws.readyState !== 0 && this.ws.readyState !== 1) {
this.close()
}
/* if (this.ws.readyState !== WebSocket.CONNECTING && this.ws.readyState !== WebSocket.OPEN) {
this.close()
} */
try {
this.ws.send(message, (error) => error && this.close())
} catch (e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,14 +156,14 @@ class JsonConnectionController(
.subscribe(self, classOf[RefactoringProtocol.ProjectRenamedNotification])
}

override def receive: Receive = {
override def receive: Receive = LoggingReceive {
case JsonRpcServer.WebConnect(webActor, _) =>
unstashAll()
context.become(connected(webActor))
case _ => stash()
}

private def connected(webActor: ActorRef): Receive = {
private def connected(webActor: ActorRef): Receive = LoggingReceive {
case req @ Request(Ping, _, Unused) =>
val handler = context.actorOf(
PingHandler.props(
Expand Down Expand Up @@ -212,7 +212,7 @@ class JsonConnectionController(
clientId: UUID,
request: Request[_, _],
receiver: ActorRef
): Receive = {
): Receive = LoggingReceive {
case _: InitializationComponentInitialized =>
logger.info("RPC session initialized for client [{}].", clientId)
val session = JsonSession(clientId, self)
Expand Down Expand Up @@ -268,7 +268,7 @@ class JsonConnectionController(
receiver: ActorRef,
cancellable: Cancellable,
rootsSoFar: List[ContentRootWithFile]
): Receive = {
): Receive = LoggingReceive {
case ContentRootManagerProtocol.ContentRootsAddedNotification(roots) =>
val allRoots = roots ++ rootsSoFar
val hasProject = roots.exists {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.enso.polyfill.timers.TimersPolyfill;
import org.enso.polyfill.web.AbortControllerPolyfill;
import org.enso.polyfill.web.EventTargetPolyfill;
import org.enso.polyfill.web.PerformancePolyfill;
import org.enso.polyfill.websocket.WebSocketPolyfill;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.HostAccess;
Expand Down Expand Up @@ -36,7 +37,7 @@ public static void main(String[] args) throws Exception {
.allowExperimentalOptions(true)
.option("js.commonjs-require", "true")
.option("js.commonjs-require-cwd", commonJsRoot);
var chromePort = 34567;// Integer.getInteger("inspectPort", -1);
var chromePort = 34567; //Integer.getInteger("inspectPort", -1);
if (chromePort > 0) {
b.option("inspect", ":" + chromePort);
}
Expand All @@ -49,6 +50,9 @@ public static void main(String[] args) throws Exception {
CompletableFuture
.supplyAsync(b::build, executor)
.thenAcceptAsync(ctx -> {
var performance = new PerformancePolyfill();
performance.initialize(ctx);

var eventTarget = new EventTargetPolyfill(executor);
eventTarget.initialize(ctx);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.enso.polyfill.web;

import java.util.Arrays;
import org.enso.polyfill.Polyfill;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Value;
import org.graalvm.polyglot.proxy.ProxyExecutable;

public final class PerformancePolyfill implements ProxyExecutable, Polyfill {

private static final String NOW = "now";

private static final String PERFORMANCE_POLYFILL_JS = "performance-polyfill.js";

public PerformancePolyfill() {
}

@Override
public void initialize(Context ctx) {
Source performancePolyfillJs = Source
.newBuilder("js", PerformancePolyfill.class.getResource(PERFORMANCE_POLYFILL_JS))
.buildLiteral();

ctx.eval(performancePolyfillJs).execute(this);
}

@Override
public Object execute(Value... arguments) {
var command = arguments[0].asString();
System.err.println(command + " " + Arrays.toString(arguments));

return switch (command) {
case NOW ->
System.currentTimeMillis();

default ->
throw new IllegalStateException(command);
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ public Object execute(Value... arguments) {
}

var wsClient = WsClient.builder()
.addHeader("Connection", "Upgrade")
.protocolConfig(protocolConfig.build())
.build();
wsClient.connect(uri, connection);
Expand Down Expand Up @@ -284,6 +283,7 @@ public void dispatchEvent(String type, Value event) {
listener.executeVoid(event);
} catch (Exception e) {
System.err.println("Error dispatching event [" + type + "] " + listener + " " + event + " " + e);
e.printStackTrace(System.err);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
(function (jvm) {

class Performance {

now() {
return jvm('now');
};
}

globalThis.performance = new Performance();

})
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package org.enso.polyfill;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.enso.polyfill.web.PerformancePolyfill;
import org.graalvm.polyglot.Context;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class PerformanceTest {

private Context context;
private ExecutorService executor;

public PerformanceTest() {
}

@Before
public void setup() throws Exception {
executor = Executors.newSingleThreadExecutor();
var eventTarget = new PerformancePolyfill();
var b = Context.newBuilder("js");

var chromePort = Integer.getInteger("inspectPort", -1);
if (chromePort > 0) {
b.option("inspect", ":" + chromePort);
}

context = CompletableFuture
.supplyAsync(() -> {
var ctx = b.build();
eventTarget.initialize(ctx);
return ctx;
}, executor)
.get();
}

@After
public void tearDown() {
executor.close();
context.close();
}

@Test
public void now() throws Exception {
var result = CompletableFuture
.supplyAsync(() -> context.eval("js", "performance.now()"), executor)
.get();

Assert.assertTrue(result.asLong() > 0);
Assert.assertTrue(result.asLong() <= System.currentTimeMillis());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.enso.jsonrpc

import akka.NotUsed
import akka.actor.{ActorRef, ActorSystem, Props}
import akka.http.scaladsl.model.headers
import akka.http.scaladsl.model.ws.{BinaryMessage, Message, TextMessage}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
Expand All @@ -10,6 +11,7 @@ import akka.stream.{Materializer, OverflowStrategy}
import com.typesafe.scalalogging.LazyLogging

import java.util.UUID

import scala.concurrent.duration._
import scala.concurrent.ExecutionContext

Expand Down Expand Up @@ -94,7 +96,7 @@ class JsonRpcServer(
override protected def serverRoute(port: Int): Route = {
val webSocketEndpoint =
path(config.path) {
get { handleWebSocketMessages(newUser(port)) }
get { handleWebSocketMessages1(newUser(port)) }
}

optionalEndpoints.foldLeft(webSocketEndpoint) { (chain, next) =>
Expand All @@ -104,6 +106,21 @@ class JsonRpcServer(

override protected def secureConfig(): Option[SecureConnectionConfig] =
config.secureConfig

// TODO[DB]: Workaround for helidon-io/helidon#8647
private def handleWebSocketMessages1(
handler: Flow[Message, Message, Any]
): Route =
extractWebSocketUpgrade { upgrade =>
complete(
upgrade
.handleMessages(handler, None)
.mapHeaders(_.map { h =>
if (h.is("connection")) headers.Connection("Upgrade") else h
})
)
}

}

object JsonRpcServer {
Expand Down

0 comments on commit f1da6ec

Please sign in to comment.