headers = Js.uncheckedCast(JsPropertyMap.of());
+ /**
+ * True to enable debug logging. At this time, only enables logging for gRPC calls.
+ */
+ @JsNullable
+ public boolean debug = false;
+
+ /**
+ * Set this to true to force the use of websockets when connecting to the deephaven instance, false to force the use
+ * of {@code fetch}.
+ *
+ * Defaults to null, indicating that the server URL should be checked to see if we connect with fetch or websockets.
+ */
+ @JsNullable
+ public Boolean useWebsockets;
+
+ // TODO (deephaven-core#6214) provide our own grpc-web library that can replace fetch
+ // /**
+ // * Optional fetch implementation to use instead of the global {@code fetch()} call, allowing callers to provide a
+ // * polyfill rather than add a new global.
+ // */
+ // @JsNullable
+ // public Function fetch;
+
public ConnectOptions() {
}
@@ -24,6 +52,18 @@ public ConnectOptions() {
public ConnectOptions(Object connectOptions) {
this();
JsPropertyMap map = Js.asPropertyMap(connectOptions);
- headers = Js.uncheckedCast(map.getAsAny("headers").asPropertyMap());
+ if (map.has("headers")) {
+ headers = Js.uncheckedCast(map.getAsAny("headers").asPropertyMap());
+ }
+ if (map.has("debug")) {
+ debug = map.getAsAny("debug").asBoolean();
+ }
+ if (map.has("useWebsockets")) {
+ useWebsockets = map.getAsAny("useWebsockets").asBoolean();
+ }
+ // TODO (deephaven-core#6214) provide our own grpc-web library that can replace fetch
+ // if (map.has("fetch")) {
+ // fetch = map.getAsAny("fetch").uncheckedCast();
+ // }
}
}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/CoreClient.java b/web/client-api/src/main/java/io/deephaven/web/client/api/CoreClient.java
index 6c6c2d2d556..7c95690175b 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/CoreClient.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/CoreClient.java
@@ -14,6 +14,7 @@
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.config_pb.ConfigurationConstantsResponse;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.config_pb_service.ConfigServiceClient;
import io.deephaven.javascript.proto.dhinternal.jspb.Map;
+import io.deephaven.web.client.api.event.HasEventHandling;
import io.deephaven.web.client.api.storage.JsStorageService;
import io.deephaven.web.client.fu.JsLog;
import io.deephaven.web.client.fu.LazyPromise;
@@ -29,8 +30,6 @@
import java.util.Objects;
import java.util.function.Consumer;
-import static io.deephaven.web.client.api.barrage.WebGrpcUtils.CLIENT_OPTIONS;
-
@JsType(namespace = "dh")
public class CoreClient extends HasEventHandling {
public static final String EVENT_CONNECT = "connect",
@@ -48,13 +47,11 @@ public class CoreClient extends HasEventHandling {
private final IdeConnection ideConnection;
public CoreClient(String serverUrl, @TsTypeRef(ConnectOptions.class) @JsOptional Object connectOptions) {
- ideConnection = new IdeConnection(serverUrl, connectOptions, true);
+ ideConnection = new IdeConnection(serverUrl, connectOptions);
// For now the only real connection is the IdeConnection, so we re-fire the auth token refresh
// event here for the UI to listen to
- ideConnection.addEventListener(EVENT_REFRESH_TOKEN_UPDATED, event -> {
- fireEvent(EVENT_REFRESH_TOKEN_UPDATED, event);
- });
+ ideConnection.addEventListener(EVENT_REFRESH_TOKEN_UPDATED, this::fireEvent);
}
private Promise getConfigs(Consumer> rpcCall,
@@ -82,20 +79,20 @@ public String getServerUrl() {
}
public Promise getAuthConfigValues() {
- return ideConnection.getConnectOptions().then(options -> {
- BrowserHeaders metadata = new BrowserHeaders();
- JsObject.keys(options.headers).forEach((key, index) -> {
- metadata.set(key, options.headers.get(key));
- return null;
- });
- return getConfigs(
- // Explicitly creating a new client, and not passing auth details, so this works pre-connection
- c -> new ConfigServiceClient(getServerUrl(), CLIENT_OPTIONS).getAuthenticationConstants(
- new AuthenticationConstantsRequest(),
- metadata,
- c::apply),
- AuthenticationConstantsResponse::getConfigValuesMap);
+ BrowserHeaders metadata = new BrowserHeaders();
+ JsPropertyMap headers = ideConnection.getOptions().headers;
+ JsObject.keys(headers).forEach((key, index) -> {
+ metadata.set(key, headers.get(key));
+ return null;
});
+ ConfigServiceClient configService = ideConnection.createClient(ConfigServiceClient::new);
+ return getConfigs(
+ // Explicitly creating a new client, and not passing auth details, so this works pre-connection
+ c -> configService.getAuthenticationConstants(
+ new AuthenticationConstantsRequest(),
+ metadata,
+ c::apply),
+ AuthenticationConstantsResponse::getConfigValuesMap);
}
public Promise login(@TsTypeRef(LoginCredentials.class) JsPropertyMap credentials) {
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/EventFn.java b/web/client-api/src/main/java/io/deephaven/web/client/api/EventFn.java
deleted file mode 100644
index a220cc4e7df..00000000000
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/EventFn.java
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending
-//
-package io.deephaven.web.client.api;
-
-import elemental2.dom.CustomEvent;
-import elemental2.dom.Event;
-import jsinterop.annotations.JsFunction;
-
-/**
- */
-@JsFunction
-public interface EventFn {
- void onEvent(CustomEvent e);
-}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/JsPartitionedTable.java b/web/client-api/src/main/java/io/deephaven/web/client/api/JsPartitionedTable.java
index aa7aca03f00..e804f178466 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/JsPartitionedTable.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/JsPartitionedTable.java
@@ -6,9 +6,6 @@
import elemental2.core.JsArray;
import elemental2.core.JsObject;
import elemental2.core.JsSet;
-import elemental2.dom.CustomEvent;
-import elemental2.dom.CustomEventInit;
-import elemental2.dom.Event;
import elemental2.promise.Promise;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.partitionedtable_pb.GetTableRequest;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.partitionedtable_pb.MergeRequest;
@@ -18,6 +15,7 @@
import io.deephaven.web.client.api.barrage.WebBarrageUtils;
import io.deephaven.web.client.api.barrage.def.ColumnDefinition;
import io.deephaven.web.client.api.barrage.def.InitialTableDefinition;
+import io.deephaven.web.client.api.event.Event;
import io.deephaven.web.client.api.lifecycle.HasLifecycle;
import io.deephaven.web.client.api.subscription.SubscriptionTableData;
import io.deephaven.web.client.api.subscription.TableSubscription;
@@ -112,10 +110,8 @@ public Promise refetch() {
fireEvent(EVENT_RECONNECT);
return null;
}, failure -> {
- CustomEventInit init = CustomEventInit.create();
- init.setDetail(failure);
unsuppressEvents();
- fireEvent(EVENT_RECONNECTFAILED, init);
+ fireEvent(EVENT_RECONNECTFAILED, failure);
suppressEvents();
return null;
});
@@ -140,20 +136,16 @@ private Promise subscribeToBaseTable() {
return promise.asPromise();
}
- private void handleKeys(Event update) {
- // noinspection unchecked
- CustomEvent event = (CustomEvent) update;
+ private void handleKeys(Event update) {
// We're only interested in added rows, send an event indicating the new keys that are available
- SubscriptionTableData eventData = event.detail;
+ SubscriptionTableData eventData = update.getDetail();
RangeSet added = eventData.getAdded().getRange();
added.indexIterator().forEachRemaining((long index) -> {
// extract the key to use
JsArray key = eventData.getColumns().map((c, p1) -> eventData.getData(index, c));
knownKeys.add(key.asList());
- CustomEventInit> init = CustomEventInit.create();
- init.setDetail(key);
- fireEvent(EVENT_KEYADDED, init);
+ fireEvent(EVENT_KEYADDED, key);
});
}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/JsTable.java b/web/client-api/src/main/java/io/deephaven/web/client/api/JsTable.java
index 21fd3ca9eff..b5d3d13e6eb 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/JsTable.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/JsTable.java
@@ -8,7 +8,6 @@
import com.vertispan.tsdefs.annotations.TsUnion;
import com.vertispan.tsdefs.annotations.TsUnionMember;
import elemental2.core.JsArray;
-import elemental2.dom.CustomEventInit;
import elemental2.promise.IThenable.ThenOnFulfilledCallbackFn;
import elemental2.promise.Promise;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.hierarchicaltable_pb.RollupRequest;
@@ -1668,9 +1667,7 @@ public void setState(final ClientTableState state) {
});
});
}
- final CustomEventInit init = CustomEventInit.create();
- init.setDetail(state);
- fireEvent(INTERNAL_EVENT_STATECHANGED, init);
+ fireEvent(INTERNAL_EVENT_STATECHANGED, state);
}
}
@@ -1739,9 +1736,7 @@ public void setSize(double s) {
// If the size changed, and we have no subscription active, fire. Otherwise, we want to let the
// subscription itself manage this, so that the size changes are synchronized with data changes,
// and consumers won't be confused by the table size not matching data.
- CustomEventInit event = CustomEventInit.create();
- event.setDetail(s);
- fireEvent(JsTable.EVENT_SIZECHANGED, event);
+ fireEvent(JsTable.EVENT_SIZECHANGED, s);
}
fireEvent(JsTable.INTERNAL_EVENT_SIZELISTENER);
}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/JsTotalsTable.java b/web/client-api/src/main/java/io/deephaven/web/client/api/JsTotalsTable.java
index 0bab10ea1d5..6801739b1fe 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/JsTotalsTable.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/JsTotalsTable.java
@@ -8,10 +8,11 @@
import com.vertispan.tsdefs.annotations.TsTypeRef;
import elemental2.core.JsArray;
import elemental2.core.JsString;
-import elemental2.dom.CustomEvent;
import elemental2.promise.Promise;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.ticket_pb.TypedTicket;
import io.deephaven.web.client.api.console.JsVariableType;
+import io.deephaven.web.client.api.event.Event;
+import io.deephaven.web.client.api.event.EventFn;
import io.deephaven.web.client.api.filter.FilterCondition;
import io.deephaven.web.client.api.subscription.AbstractTableSubscription;
import io.deephaven.web.client.api.subscription.ViewportData;
@@ -223,7 +224,7 @@ public boolean removeEventListener(String name, EventFn callback) {
}
@JsMethod
- public Promise> nextEvent(String eventName, Double timeoutInMillis) {
+ public Promise> nextEvent(String eventName, Double timeoutInMillis) {
return wrappedTable.nextEvent(eventName, timeoutInMillis);
}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/QueryConnectable.java b/web/client-api/src/main/java/io/deephaven/web/client/api/QueryConnectable.java
index 1f4fc572f91..1394069e0b7 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/QueryConnectable.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/QueryConnectable.java
@@ -6,10 +6,12 @@
import com.vertispan.tsdefs.annotations.TsIgnore;
import elemental2.core.JsArray;
import elemental2.core.JsSet;
-import elemental2.dom.CustomEventInit;
-import elemental2.dom.DomGlobal;
import elemental2.promise.Promise;
+import io.deephaven.javascript.proto.dhinternal.grpcweb.Grpc;
+import io.deephaven.javascript.proto.dhinternal.grpcweb.client.RpcOptions;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.session_pb.TerminationNotificationResponse;
+import io.deephaven.web.client.api.event.HasEventHandling;
+import io.deephaven.web.client.api.grpc.MultiplexedWebsocketTransport;
import io.deephaven.web.client.ide.IdeSession;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.console_pb.*;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.ticket_pb.Ticket;
@@ -26,6 +28,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.function.BiFunction;
import static io.deephaven.web.client.ide.IdeConnection.HACK_CONNECTION_FAILURE;
import static io.deephaven.web.shared.fu.PromiseLike.CANCELLATION_MESSAGE;
@@ -51,9 +54,9 @@ public QueryConnectable() {
this.connection = JsLazy.of(() -> new WorkerConnection(this));
}
- public abstract Promise getConnectToken();
+ public abstract ConnectToken getToken();
- public abstract Promise getConnectOptions();
+ public abstract ConnectOptions getOptions();
@Deprecated
public void notifyConnectionError(ResponseStreamWrapper.Status status) {
@@ -62,12 +65,10 @@ public void notifyConnectionError(ResponseStreamWrapper.Status status) {
}
notifiedConnectionError = true;
- CustomEventInit> event = CustomEventInit.create();
- event.setDetail(JsPropertyMap.of(
+ fireEvent(HACK_CONNECTION_FAILURE, JsPropertyMap.of(
"status", status.getCode(),
"details", status.getDetails(),
"metadata", status.getMetadata()));
- fireEvent(HACK_CONNECTION_FAILURE, event);
JsLog.warn(
"The event dh.IdeConnection.HACK_CONNECTION_FAILURE is deprecated and will be removed in a later release");
}
@@ -244,4 +245,28 @@ public void disconnected() {
}
public abstract void notifyServerShutdown(TerminationNotificationResponse success);
+
+ public boolean useWebsockets() {
+ Boolean useWebsockets = getOptions().useWebsockets;
+ if (useWebsockets == null) {
+ useWebsockets = getServerUrl().startsWith("http:");
+ }
+ return useWebsockets;
+ }
+
+ public T createClient(BiFunction constructor) {
+ return constructor.apply(getServerUrl(), makeRpcOptions());
+ }
+
+ public RpcOptions makeRpcOptions() {
+ RpcOptions options = RpcOptions.create();
+ options.setDebug(getOptions().debug);
+ if (useWebsockets()) {
+ // Replace with our custom websocket impl, with fallback to the built-in one
+ options.setTransport(o -> new MultiplexedWebsocketTransport(o, () -> {
+ Grpc.setDefaultTransport.onInvoke(Grpc.WebsocketTransport.onInvoke());
+ }));
+ }
+ return options;
+ }
}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/WorkerConnection.java b/web/client-api/src/main/java/io/deephaven/web/client/api/WorkerConnection.java
index abe4c914bb0..281d3173fb9 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/WorkerConnection.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/WorkerConnection.java
@@ -10,13 +10,13 @@
import elemental2.core.JsSet;
import elemental2.core.JsWeakMap;
import elemental2.core.Uint8Array;
-import elemental2.dom.CustomEventInit;
import elemental2.dom.DomGlobal;
import elemental2.promise.Promise;
import io.deephaven.javascript.proto.dhinternal.arrow.flight.protocol.browserflight_pb_service.BrowserFlightServiceClient;
import io.deephaven.javascript.proto.dhinternal.arrow.flight.protocol.flight_pb.FlightData;
import io.deephaven.javascript.proto.dhinternal.arrow.flight.protocol.flight_pb_service.FlightServiceClient;
import io.deephaven.javascript.proto.dhinternal.browserheaders.BrowserHeaders;
+import io.deephaven.javascript.proto.dhinternal.grpcweb.client.ClientRpcOptions;
import io.deephaven.javascript.proto.dhinternal.grpcweb.grpc.Code;
import io.deephaven.javascript.proto.dhinternal.grpcweb.grpc.UnaryOutput;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.application_pb.FieldInfo;
@@ -64,6 +64,7 @@
import io.deephaven.web.client.api.console.JsVariableChanges;
import io.deephaven.web.client.api.console.JsVariableDefinition;
import io.deephaven.web.client.api.console.JsVariableType;
+import io.deephaven.web.client.api.event.HasEventHandling;
import io.deephaven.web.client.api.grpc.UnaryWithHeaders;
import io.deephaven.web.client.api.i18n.JsTimeZone;
import io.deephaven.web.client.api.impl.TicketAndPromise;
@@ -110,7 +111,6 @@
import java.util.stream.Collectors;
import static io.deephaven.web.client.api.CoreClient.EVENT_REFRESH_TOKEN_UPDATED;
-import static io.deephaven.web.client.api.barrage.WebGrpcUtils.CLIENT_OPTIONS;
/**
* Non-exported class, manages the connection to a given worker server. Exported types like QueryInfo and Table will
@@ -159,6 +159,7 @@ private enum State {
}
private final QueryConnectable> info;
+ private final ClientRpcOptions options = ClientRpcOptions.create();
private final ClientConfiguration config;
private final ReconnectState newSessionReconnect;
private final TableReviver reviver;
@@ -204,28 +205,22 @@ private enum State {
public WorkerConnection(QueryConnectable> info) {
this.info = info;
+
this.config = new ClientConfiguration();
state = State.Connecting;
this.reviver = new TableReviver(this);
- sessionServiceClient = new SessionServiceClient(info.getServerUrl(), CLIENT_OPTIONS);
- tableServiceClient = new TableServiceClient(info.getServerUrl(), CLIENT_OPTIONS);
- consoleServiceClient = new ConsoleServiceClient(info.getServerUrl(), CLIENT_OPTIONS);
- flightServiceClient = new FlightServiceClient(info.getServerUrl(), CLIENT_OPTIONS);
- applicationServiceClient =
- new ApplicationServiceClient(info.getServerUrl(), CLIENT_OPTIONS);
- browserFlightServiceClient =
- new BrowserFlightServiceClient(info.getServerUrl(), CLIENT_OPTIONS);
- inputTableServiceClient =
- new InputTableServiceClient(info.getServerUrl(), CLIENT_OPTIONS);
- objectServiceClient = new ObjectServiceClient(info.getServerUrl(), CLIENT_OPTIONS);
- partitionedTableServiceClient =
- new PartitionedTableServiceClient(info.getServerUrl(), CLIENT_OPTIONS);
- storageServiceClient = new StorageServiceClient(info.getServerUrl(), CLIENT_OPTIONS);
- configServiceClient = new ConfigServiceClient(info.getServerUrl(), CLIENT_OPTIONS);
- hierarchicalTableServiceClient =
- new HierarchicalTableServiceClient(info.getServerUrl(), CLIENT_OPTIONS);
-
- // builder.setConnectionErrorHandler(msg -> info.failureHandled(String.valueOf(msg)));
+ sessionServiceClient = info.createClient(SessionServiceClient::new);
+ tableServiceClient = info.createClient(TableServiceClient::new);
+ consoleServiceClient = info.createClient(ConsoleServiceClient::new);
+ flightServiceClient = info.createClient(FlightServiceClient::new);
+ applicationServiceClient = info.createClient(ApplicationServiceClient::new);
+ browserFlightServiceClient = info.createClient(BrowserFlightServiceClient::new);
+ inputTableServiceClient = info.createClient(InputTableServiceClient::new);
+ objectServiceClient = info.createClient(ObjectServiceClient::new);
+ partitionedTableServiceClient = info.createClient(PartitionedTableServiceClient::new);
+ storageServiceClient = info.createClient(StorageServiceClient::new);
+ configServiceClient = info.createClient(ConfigServiceClient::new);
+ hierarchicalTableServiceClient = info.createClient(HierarchicalTableServiceClient::new);
newSessionReconnect = new ReconnectState(this::connectToWorker);
@@ -253,21 +248,13 @@ private void connectToWorker() {
if (metadata().has(FLIGHT_AUTH_HEADER_NAME)) {
return authUpdate().then(ignore -> Promise.resolve(Boolean.FALSE));
}
- return Promise.all(
- info.getConnectToken().then(authToken -> {
- // set the proposed initial token and make the first call
- metadata.set(FLIGHT_AUTH_HEADER_NAME,
- (authToken.getType() + " " + authToken.getValue()).trim());
- return Promise.resolve(authToken);
- }),
- info.getConnectOptions().then(options -> {
- // set other specified headers, if any
- JsObject.keys(options.headers).forEach((key, index) -> {
- metadata.set(key, options.headers.get(key));
- return null;
- });
- return Promise.resolve(options);
- })).then(ignore -> authUpdate()).then(ignore -> Promise.resolve(Boolean.TRUE));
+ metadata.set(FLIGHT_AUTH_HEADER_NAME,
+ (info.getToken().getType() + " " + info.getToken().getValue()).trim());
+ JsObject.keys(info.getOptions().headers).forEach((key, index) -> {
+ metadata.set(key, info.getOptions().headers.get(key));
+ return null;
+ });
+ return authUpdate().then(ignore -> Promise.resolve(Boolean.TRUE));
}).then(newSession -> {
// subscribe to fatal errors
subscribeToTerminationNotification();
@@ -463,7 +450,9 @@ private Promise authUpdate() {
scheduledAuthUpdate = null;
}
return UnaryWithHeaders.call(
- this, ConfigService.GetConfigurationConstants, new ConfigurationConstantsRequest())
+ info.getServerUrl(),
+ metadata(), info.makeRpcOptions(), ConfigService.GetConfigurationConstants,
+ new ConfigurationConstantsRequest())
.then(result -> {
BrowserHeaders headers = result.getHeaders();
// unchecked cast is required here due to "aliasing" in ts/webpack resulting in BrowserHeaders !=
@@ -475,9 +464,8 @@ this, ConfigService.GetConfigurationConstants, new ConfigurationConstantsRequest
if (!existing.getAt(0).equals(authorization.getAt(0))) {
// use this new token
metadata().set(FLIGHT_AUTH_HEADER_NAME, authorization);
- CustomEventInit init = CustomEventInit.create();
- init.setDetail(new JsRefreshToken(authorization.getAt(0), sessionTimeoutMs));
- info.fireEvent(EVENT_REFRESH_TOKEN_UPDATED, init);
+ info.fireEvent(EVENT_REFRESH_TOKEN_UPDATED,
+ new JsRefreshToken(authorization.getAt(0), sessionTimeoutMs));
}
}
@@ -1002,7 +990,7 @@ public BrowserHeaders metadata() {
}
public BiDiStream.Factory streamFactory() {
- return new BiDiStream.Factory<>(this::metadata, config::newTicketInt);
+ return new BiDiStream.Factory<>(info.useWebsockets(), this::metadata, config::newTicketInt);
}
public Promise newTable(String[] columnNames, String[] types, Object[][] data, String userTimeZone,
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/barrage/WebGrpcUtils.java b/web/client-api/src/main/java/io/deephaven/web/client/api/barrage/WebGrpcUtils.java
deleted file mode 100644
index 5d6ea33527e..00000000000
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/barrage/WebGrpcUtils.java
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending
-//
-package io.deephaven.web.client.api.barrage;
-
-import elemental2.dom.DomGlobal;
-import io.deephaven.javascript.proto.dhinternal.grpcweb.Grpc;
-import io.deephaven.web.client.api.grpc.MultiplexedWebsocketTransport;
-import jsinterop.base.JsPropertyMap;
-
-/**
- * Holds some static details, must be initialized before any calls can be made. When our gRPC-web client is redone to
- * support interceptors/etc, this will likely no longer need to exist
- */
-public class WebGrpcUtils {
- /**
- * One place to change all debug flags in the app.
- */
- public static final Object CLIENT_OPTIONS = JsPropertyMap.of(
- "debug", false);
-
- /**
- * True if https isn't available (as a proxy for h2).
- */
- public static final boolean USE_WEBSOCKETS;
-
- static {
- // TODO configurable, let us support this even when ssl?
- if (DomGlobal.window.location.protocol.equals("http:")) {
- USE_WEBSOCKETS = true;
- Grpc.setDefaultTransport.onInvoke(options -> new MultiplexedWebsocketTransport(options, () -> {
- Grpc.setDefaultTransport.onInvoke(Grpc.WebsocketTransport.onInvoke());
- }));
- } else {
- USE_WEBSOCKETS = false;
- }
- }
-}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/barrage/stream/BiDiStream.java b/web/client-api/src/main/java/io/deephaven/web/client/api/barrage/stream/BiDiStream.java
index 758fe62f20c..5febd0a9fa4 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/barrage/stream/BiDiStream.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/barrage/stream/BiDiStream.java
@@ -16,8 +16,6 @@
import java.util.function.IntSupplier;
import java.util.function.Supplier;
-import static io.deephaven.web.client.api.barrage.WebGrpcUtils.USE_WEBSOCKETS;
-
public abstract class BiDiStream {
public interface BiDiStreamFactory {
/**
@@ -38,10 +36,12 @@ public interface NextStreamMessageFactory {
void nextStreamMessage(Req nextPayload, BrowserHeaders headers, JsBiConsumer callback);
}
public static class Factory {
+ private final boolean useWebsockets;
private final Supplier headers;
private final IntSupplier nextIntTicket;
- public Factory(Supplier headers, IntSupplier nextIntTicket) {
+ public Factory(boolean useWebsockets, Supplier headers, IntSupplier nextIntTicket) {
+ this.useWebsockets = useWebsockets;
this.headers = headers;
this.nextIntTicket = nextIntTicket;
}
@@ -51,7 +51,7 @@ public BiDiStream create(
OpenStreamFactory openEmulatedStream,
NextStreamMessageFactory nextEmulatedStream,
ReqT emptyReq) {
- if (USE_WEBSOCKETS) {
+ if (useWebsockets) {
return websocket(bidirectionalStream.openBiDiStream(headers.get()));
} else {
return new EmulatedBiDiStream<>(
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/batch/RequestBatcher.java b/web/client-api/src/main/java/io/deephaven/web/client/api/batch/RequestBatcher.java
index 9d10b006c81..10631549a4c 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/batch/RequestBatcher.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/batch/RequestBatcher.java
@@ -3,7 +3,6 @@
//
package io.deephaven.web.client.api.batch;
-import elemental2.dom.CustomEventInit;
import elemental2.promise.Promise;
import elemental2.promise.Promise.PromiseExecutorCallbackFn.RejectCallbackFn;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.ticket_pb.Ticket;
@@ -341,7 +340,6 @@ public Promise sendRequest() {
}
private void failTable(JsTable t, String failureMessage) {
- final CustomEventInit event = CustomEventInit.create();
ClientTableState best = t.state();
for (ClientTableState state : best.reversed()) {
if (allStates().anyMatch(state::equals)) {
@@ -350,9 +348,6 @@ private void failTable(JsTable t, String failureMessage) {
}
}
- event.setDetail(JsPropertyMap.of(
- "errorMessage", failureMessage,
- "configuration", best.toJs()));
try {
t.rollback();
} catch (Exception e) {
@@ -360,7 +355,9 @@ private void failTable(JsTable t, String failureMessage) {
"An exception occurred trying to rollback the table. This means that there will be no ticking data until the table configuration is applied again in a way that makes sense. See IDS-5199 for more detail.",
e);
}
- t.fireEvent(CoreClient.EVENT_REQUEST_FAILED, event);
+ t.fireEvent(CoreClient.EVENT_REQUEST_FAILED, JsPropertyMap.of(
+ "errorMessage", failureMessage,
+ "configuration", best.toJs()));
}
private void failed(RejectCallbackFn reject, String fail) {
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/event/Event.java b/web/client-api/src/main/java/io/deephaven/web/client/api/event/Event.java
new file mode 100644
index 00000000000..8749a68c755
--- /dev/null
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/event/Event.java
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending
+//
+package io.deephaven.web.client.api.event;
+
+import com.vertispan.tsdefs.annotations.TsInterface;
+import com.vertispan.tsdefs.annotations.TsName;
+import jsinterop.annotations.JsNullable;
+import jsinterop.annotations.JsProperty;
+
+/**
+ * Similar to the browser {@code CustomEvent} type, this class holds only the type of the event, and optionally some
+ * details about the event.
+ *
+ * @param the type of the event detail
+ */
+@TsInterface
+@TsName(namespace = "dh")
+public class Event {
+ private final String type;
+ private final T detail;
+
+ public Event(String type, T detail) {
+ this.type = type;
+ this.detail = detail;
+ }
+
+ @JsProperty
+ public String getType() {
+ return type;
+ }
+
+ @JsProperty
+ @JsNullable
+ public T getDetail() {
+ return detail;
+ }
+}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/event/EventFn.java b/web/client-api/src/main/java/io/deephaven/web/client/api/event/EventFn.java
new file mode 100644
index 00000000000..314c1d26795
--- /dev/null
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/event/EventFn.java
@@ -0,0 +1,15 @@
+//
+// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending
+//
+package io.deephaven.web.client.api.event;
+
+import jsinterop.annotations.JsFunction;
+
+/**
+ * Event handler function. In JS/TS, this will only show up as a function type when used, but these docs will never be
+ * visible.
+ */
+@JsFunction
+public interface EventFn {
+ void onEvent(Event e);
+}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/HasEventHandling.java b/web/client-api/src/main/java/io/deephaven/web/client/api/event/HasEventHandling.java
similarity index 81%
rename from web/client-api/src/main/java/io/deephaven/web/client/api/HasEventHandling.java
rename to web/client-api/src/main/java/io/deephaven/web/client/api/event/HasEventHandling.java
index 16cb9bfe549..c4fc78234d9 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/HasEventHandling.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/event/HasEventHandling.java
@@ -1,16 +1,15 @@
//
// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending
//
-package io.deephaven.web.client.api;
+package io.deephaven.web.client.api.event;
import com.vertispan.tsdefs.annotations.TsInterface;
import com.vertispan.tsdefs.annotations.TsName;
import elemental2.core.JsArray;
import elemental2.core.JsObject;
-import elemental2.dom.CustomEvent;
-import elemental2.dom.CustomEventInit;
import elemental2.dom.DomGlobal;
import elemental2.promise.Promise;
+import io.deephaven.web.client.api.CoreClient;
import io.deephaven.web.client.fu.JsLog;
import io.deephaven.web.client.fu.LazyPromise;
import io.deephaven.web.shared.fu.RemoverFn;
@@ -70,7 +69,7 @@ final class WrappedCallback implements EventFn {
private EventFn self;
@Override
- public void onEvent(CustomEvent e) {
+ public void onEvent(Event e) {
removeEventListener(name, self);
callback.onEvent(e);
}
@@ -100,14 +99,14 @@ public void addEventListenerOneShot(EventPair>... pairs) {
return;
}
seen[0] = true;
- pair.callback.onEvent((CustomEvent) e);
+ pair.callback.onEvent((Event) e);
});
}
}
@JsMethod
- public Promise> nextEvent(String eventName, @JsOptional Double timeoutInMillis) {
- LazyPromise> promise = new LazyPromise<>();
+ public Promise> nextEvent(String eventName, @JsOptional Double timeoutInMillis) {
+ LazyPromise> promise = new LazyPromise<>();
addEventListenerOneShot(eventName, promise::succeed);
@@ -158,31 +157,26 @@ public boolean removeEventListener(String name, EventFn callback) {
}
public void fireEvent(String type) {
- fireEvent(type, CustomEventInit.create());
+ fireEvent(new Event<>(type, null));
}
- public void fireEventWithDetail(String type, @DoNotAutobox T detail) {
- final CustomEventInit evt = CustomEventInit.create();
- evt.setDetail(detail);
- fireEvent(type, evt);
+ public void fireEvent(String type, @DoNotAutobox T detail) {
+ fireEvent(new Event<>(type, detail));
}
- public void fireEvent(String type, CustomEventInit init) {
- fireEvent(type, new CustomEvent<>(type, init));
- }
-
- public void fireEvent(String type, CustomEvent e) {
+ public void fireEvent(Event e) {
if (suppress) {
- JsLog.debug("Event suppressed", type, e);
+ JsLog.debug("Event suppressed", e.getType(), e);
return;
}
- if (map.has(e.type)) {
- final JsArray> callbacks = Js.cast(JsArray.from((JsArrayLike>) map.get(e.type)));
+ if (map.has(e.getType())) {
+ final JsArray> callbacks = Js.cast(JsArray.from((JsArrayLike>) map.get(e.getType())));
callbacks.forEach((item, ind) -> {
try {
item.onEvent(e);
} catch (Throwable t) {
- DomGlobal.console.error(logPrefix() + "User callback (", item, ") of type ", type, " failed: ", t);
+ DomGlobal.console.error(logPrefix() + "User callback (", item, ") of type ", e.getType(),
+ " failed: ", t);
t.printStackTrace();
}
return true;
@@ -198,11 +192,11 @@ public void fireCriticalEvent(String type) {
}
}
- public void fireCriticalEvent(String type, CustomEventInit init) {
+ public void fireCriticalEvent(String type, T detail) {
if (hasListeners(type)) {
- fireEvent(type, init);
+ fireEvent(type, detail);
} else {
- DomGlobal.console.error(logPrefix(), init.getDetail(),
+ DomGlobal.console.error(logPrefix(), detail,
"(to prevent this log message, handle the " + type + " event)");
}
}
@@ -211,9 +205,7 @@ public void failureHandled(String failure) {
if (failure == null) {
return;
}
- final CustomEventInit event = CustomEventInit.create();
- event.setDetail(failure);
- fireCriticalEvent(CoreClient.EVENT_REQUEST_FAILED, event);
+ fireCriticalEvent(CoreClient.EVENT_REQUEST_FAILED, failure);
}
public void suppressEvents() {
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/grpc/UnaryWithHeaders.java b/web/client-api/src/main/java/io/deephaven/web/client/api/grpc/UnaryWithHeaders.java
index 2b82a40d2b8..4b6316631b5 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/grpc/UnaryWithHeaders.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/grpc/UnaryWithHeaders.java
@@ -5,31 +5,36 @@
import elemental2.promise.IThenable;
import elemental2.promise.Promise;
+import io.deephaven.javascript.proto.dhinternal.browserheaders.BrowserHeaders;
import io.deephaven.javascript.proto.dhinternal.grpcweb.Grpc;
+import io.deephaven.javascript.proto.dhinternal.grpcweb.client.RpcOptions;
import io.deephaven.javascript.proto.dhinternal.grpcweb.grpc.Code;
import io.deephaven.javascript.proto.dhinternal.grpcweb.unary.UnaryOutput;
import io.deephaven.javascript.proto.dhinternal.grpcweb.unary.UnaryRpcOptions;
-import io.deephaven.web.client.api.WorkerConnection;
public class UnaryWithHeaders {
/**
* Improbable-eng's grpc-web implementation doesn't pass headers to api callers - this changes the contract a bit so
* that we can get a typed UnaryOutput with the headers/trailers intact.
- *
- * @param connection provides access to the metadata and the server url
+ *
+ * @param host the server to connect to
+ * @param metadata gRPC metadata to set on the request
+ * @param options options to use when sending the request
* @param methodDescriptor the service method to invoke
* @return a promise that will resolve to the response plus headers/trailers, or reject with the headers/trailers
* @param type of the message object
*/
- public static Promise> call(WorkerConnection connection, Object methodDescriptor,
+ public static Promise> call(String host, BrowserHeaders metadata, RpcOptions options,
+ Object methodDescriptor,
Req request) {
return new Promise<>((resolve, reject) -> {
UnaryRpcOptions props = UnaryRpcOptions.create();
- props.setHost(connection.configServiceClient().serviceHost);
- props.setMetadata(connection.metadata());
- props.setTransport(null);// ts doesn't expose these two, stick with defaults for now
- props.setDebug(false);
+ props.setRequest(request);
+ props.setHost(host);
+ props.setMetadata(metadata);
+ props.setTransport(options.getTransport());
+ props.setDebug(options.isDebug());
props.setOnEnd(response -> {
if (response.getStatus() != Code.OK) {
reject.onInvoke(response);
@@ -37,7 +42,6 @@ public static Promise> call(WorkerConnection connect
resolve.onInvoke((IThenable>) response);
}
});
- props.setRequest(request);
Grpc.unary.onInvoke(methodDescriptor, props);
});
}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/lifecycle/HasLifecycle.java b/web/client-api/src/main/java/io/deephaven/web/client/api/lifecycle/HasLifecycle.java
index 3fd9f2c4923..84e54e63bca 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/lifecycle/HasLifecycle.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/lifecycle/HasLifecycle.java
@@ -3,11 +3,9 @@
//
package io.deephaven.web.client.api.lifecycle;
-import elemental2.dom.CustomEvent;
-import elemental2.dom.CustomEventInit;
import elemental2.promise.Promise;
-import io.deephaven.web.client.api.HasEventHandling;
import io.deephaven.web.client.api.JsTable;
+import io.deephaven.web.client.api.event.HasEventHandling;
import io.deephaven.web.client.fu.JsLog;
import static io.deephaven.web.client.api.JsTable.EVENT_RECONNECTFAILED;
@@ -28,10 +26,8 @@ public abstract class HasLifecycle extends HasEventHandling {
*/
public void die(Object error) {
JsLog.debug("Die!", this, error);
- final CustomEventInit init = CustomEventInit.create();
- init.setDetail(error);
unsuppressEvents();
- fireEvent(EVENT_RECONNECTFAILED, init);
+ fireEvent(EVENT_RECONNECTFAILED, error);
suppressEvents();
}
@@ -78,9 +74,9 @@ public Promise nextReconnect() {
addEventListenerOneShot(
HasEventHandling.EventPair.of(JsTable.EVENT_RECONNECT, event -> resolve.onInvoke((Void) null)),
HasEventHandling.EventPair.of(JsTable.EVENT_DISCONNECT,
- event -> reject.onInvoke(((CustomEvent) event).detail)),
+ event -> reject.onInvoke(event.getDetail())),
HasEventHandling.EventPair.of(EVENT_RECONNECTFAILED,
- event -> reject.onInvoke(((CustomEvent) event).detail)));
+ event -> reject.onInvoke(event.getDetail())));
});
}
}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/subscription/AbstractTableSubscription.java b/web/client-api/src/main/java/io/deephaven/web/client/api/subscription/AbstractTableSubscription.java
index 55ea471c752..f690d3df66f 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/subscription/AbstractTableSubscription.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/subscription/AbstractTableSubscription.java
@@ -6,7 +6,6 @@
import com.google.flatbuffers.FlatBufferBuilder;
import com.vertispan.tsdefs.annotations.TsIgnore;
import elemental2.core.JsArray;
-import elemental2.dom.CustomEventInit;
import io.deephaven.barrage.flatbuf.BarrageMessageType;
import io.deephaven.barrage.flatbuf.BarrageSubscriptionRequest;
import io.deephaven.extensions.barrage.BarrageSubscriptionOptions;
@@ -14,7 +13,6 @@
import io.deephaven.javascript.proto.dhinternal.arrow.flight.protocol.flight_pb.FlightData;
import io.deephaven.web.client.api.Column;
import io.deephaven.web.client.api.Format;
-import io.deephaven.web.client.api.HasEventHandling;
import io.deephaven.web.client.api.JsRangeSet;
import io.deephaven.web.client.api.LongWrapper;
import io.deephaven.web.client.api.TableData;
@@ -26,6 +24,7 @@
import io.deephaven.web.client.api.barrage.data.WebBarrageSubscription;
import io.deephaven.web.client.api.barrage.stream.BiDiStream;
import io.deephaven.web.client.api.barrage.stream.ResponseStreamWrapper;
+import io.deephaven.web.client.api.event.HasEventHandling;
import io.deephaven.web.client.fu.JsSettings;
import io.deephaven.web.client.state.ClientTableState;
import io.deephaven.web.shared.data.RangeSet;
@@ -243,9 +242,7 @@ protected void notifyUpdate(RangeSet rowsAdded, RangeSet rowsRemoved, RangeSet t
rowsRemoved,
totalMods,
shifted);
- CustomEventInit event = CustomEventInit.create();
- event.setDetail(detail);
- fireEvent(TableSubscription.EVENT_UPDATED, event);
+ fireEvent(TableSubscription.EVENT_UPDATED, detail);
}
public static class SubscriptionRow implements TableData.Row {
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/subscription/TableViewportSubscription.java b/web/client-api/src/main/java/io/deephaven/web/client/api/subscription/TableViewportSubscription.java
index d33c47f51c7..e745899cb5a 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/subscription/TableViewportSubscription.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/subscription/TableViewportSubscription.java
@@ -7,8 +7,6 @@
import com.vertispan.tsdefs.annotations.TsName;
import com.vertispan.tsdefs.annotations.TsTypeRef;
import elemental2.core.JsArray;
-import elemental2.dom.CustomEvent;
-import elemental2.dom.CustomEventInit;
import elemental2.promise.Promise;
import io.deephaven.barrage.flatbuf.BarrageMessageType;
import io.deephaven.barrage.flatbuf.BarrageSnapshotRequest;
@@ -28,6 +26,7 @@
import io.deephaven.web.client.api.barrage.WebBarrageUtils;
import io.deephaven.web.client.api.barrage.data.WebBarrageSubscription;
import io.deephaven.web.client.api.barrage.stream.BiDiStream;
+import io.deephaven.web.client.api.event.Event;
import io.deephaven.web.client.fu.JsLog;
import io.deephaven.web.client.fu.LazyPromise;
import io.deephaven.web.client.state.ClientTableState;
@@ -137,16 +136,14 @@ protected void sendFirstSubscriptionRequest() {
protected void notifyUpdate(RangeSet rowsAdded, RangeSet rowsRemoved, RangeSet totalMods, ShiftedRange[] shifted) {
// viewport subscriptions are sometimes required to notify of size change events
if (rowsAdded.size() != rowsRemoved.size() && originalActive) {
- fireEventWithDetail(JsTable.EVENT_SIZECHANGED, size());
+ fireEvent(JsTable.EVENT_SIZECHANGED, size());
}
UpdateEventData detail = new ViewportEventData(barrageSubscription, rowStyleColumn, getColumns(), rowsAdded,
rowsRemoved, totalMods, shifted);
detail.setOffset(this.viewportRowSet.getFirstRow());
this.viewportData = detail;
- CustomEventInit event = CustomEventInit.create();
- event.setDetail(detail);
- refire(new CustomEvent<>(EVENT_UPDATED, event));
+ refire(new Event<>(EVENT_UPDATED, detail));
if (hasListeners(EVENT_ROWADDED) || hasListeners(EVENT_ROWREMOVED) || hasListeners(EVENT_ROWUPDATED)) {
RangeSet modifiedCopy = totalMods.copy();
@@ -175,9 +172,8 @@ protected void notifyUpdate(RangeSet rowsAdded, RangeSet rowsRemoved, RangeSet t
private void fireLegacyEventOnRowsetEntries(String eventName, UpdateEventData updateEventData, RangeSet rowset) {
if (hasListeners(eventName)) {
rowset.indexIterator().forEachRemaining((long row) -> {
- CustomEventInit> addedEvent = CustomEventInit.create();
- addedEvent.setDetail(wrap((SubscriptionRow) updateEventData.getRows().getAt((int) row), (int) row));
- fireEvent(eventName, addedEvent);
+ JsPropertyMap> detail = wrap((SubscriptionRow) updateEventData.getRows().getAt((int) row), (int) row);
+ fireEvent(eventName, detail);
});
}
}
@@ -188,26 +184,16 @@ private static JsPropertyMap> wrap(SubscriptionRow rowObj, int row) {
@Override
public void fireEvent(String type) {
- refire(new CustomEvent<>(type));
+ refire(new Event<>(type, null));
}
@Override
- public void fireEventWithDetail(String type, T detail) {
- CustomEventInit init = CustomEventInit.create();
- init.setDetail(detail);
- refire(new CustomEvent(type, init));
+ public void fireEvent(String type, T detail) {
+ refire(new Event(type, detail));
}
@Override
- public void fireEvent(String type, CustomEventInit init) {
- refire(new CustomEvent(type, init));
- }
-
- @Override
- public void fireEvent(String type, CustomEvent e) {
- if (!type.equals(e.type)) {
- throw new IllegalArgumentException(type + " != " + e.type);
- }
+ public void fireEvent(Event e) {
refire(e);
}
@@ -228,16 +214,16 @@ public boolean hasListeners(String name) {
* @param e the event to fire
* @param the type of the custom event data
*/
- private void refire(CustomEvent e) {
+ private void refire(Event e) {
// explicitly calling super.fireEvent to avoid calling ourselves recursively
- super.fireEvent(e.type, e);
+ super.fireEvent(e);
if (originalActive && initialState == original.state()) {
// When these fail to match, it probably means that the original's state was paused, but we're still
// holding on to it. Since we haven't been internalClose()d yet, that means we're still waiting for
// the new state to resolve or fail, so we can be restored, or stopped. In theory, we should put this
// assert back, and make the pause code also tell us to pause.
// assert initialState == original.state() : "Table owning this viewport subscription forgot to release it";
- original.fireEvent(e.type, e);
+ original.fireEvent(e);
}
}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/tree/JsTreeTable.java b/web/client-api/src/main/java/io/deephaven/web/client/api/tree/JsTreeTable.java
index 72e7ea11116..128c26fa7e0 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/tree/JsTreeTable.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/tree/JsTreeTable.java
@@ -10,8 +10,6 @@
import elemental2.core.JsArray;
import elemental2.core.JsObject;
import elemental2.core.Uint8Array;
-import elemental2.dom.CustomEvent;
-import elemental2.dom.CustomEventInit;
import elemental2.dom.DomGlobal;
import elemental2.promise.IThenable;
import elemental2.promise.Promise;
@@ -31,6 +29,7 @@
import io.deephaven.web.client.api.barrage.def.ColumnDefinition;
import io.deephaven.web.client.api.barrage.def.InitialTableDefinition;
import io.deephaven.web.client.api.barrage.stream.ResponseStreamWrapper;
+import io.deephaven.web.client.api.event.Event;
import io.deephaven.web.client.api.filter.FilterCondition;
import io.deephaven.web.client.api.impl.TicketAndPromise;
import io.deephaven.web.client.api.lifecycle.HasLifecycle;
@@ -574,9 +573,7 @@ protected void notifyUpdate(RangeSet rowsAdded, RangeSet rowsRemoved, RangeSet t
new TreeViewportDataImpl(barrageSubscription, rowStyleColumn, getColumns(), rowsAdded,
rowsRemoved, totalMods, shifted);
detail.setOffset(this.serverViewport.getFirstRow());
- CustomEventInit event = CustomEventInit.create();
- event.setDetail(detail);
- fireEvent(EVENT_UPDATED, event);
+ fireEvent(EVENT_UPDATED, detail);
}
}
@@ -660,9 +657,9 @@ private void replaceSubscription(RebuildStep step) {
TreeSubscription subscription = new TreeSubscription(state, connection);
subscription.addEventListener(TreeSubscription.EVENT_UPDATED,
- (CustomEvent data) -> {
+ (Event data) -> {
TreeSubscription.TreeViewportDataImpl detail =
- (TreeSubscription.TreeViewportDataImpl) data.detail;
+ (TreeSubscription.TreeViewportDataImpl) data.getDetail();
handleUpdate(nextSort, nextFilters, detail, alwaysFireEvent);
});
@@ -705,9 +702,7 @@ private void handleUpdate(List nextSort, List nextFilters
this.filters = nextFilters;
if (fireEvent) {
- CustomEventInit updatedEvent = CustomEventInit.create();
- updatedEvent.setDetail(viewportData);
- fireEvent(EVENT_UPDATED, updatedEvent);
+ fireEvent(EVENT_UPDATED, viewportData);
}
}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/widget/JsWidget.java b/web/client-api/src/main/java/io/deephaven/web/client/api/widget/JsWidget.java
index e0a35c53791..68d55d86c34 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/widget/JsWidget.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/widget/JsWidget.java
@@ -10,15 +10,14 @@
import elemental2.core.ArrayBufferView;
import elemental2.core.JsArray;
import elemental2.core.Uint8Array;
-import elemental2.dom.CustomEventInit;
import elemental2.promise.Promise;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.object_pb.*;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.ticket_pb.Ticket;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.ticket_pb.TypedTicket;
-import io.deephaven.web.client.api.HasEventHandling;
import io.deephaven.web.client.api.ServerObject;
import io.deephaven.web.client.api.WorkerConnection;
import io.deephaven.web.client.api.barrage.stream.BiDiStream;
+import io.deephaven.web.client.api.event.HasEventHandling;
import jsinterop.annotations.JsMethod;
import jsinterop.annotations.JsOptional;
import jsinterop.annotations.JsOverlay;
@@ -153,9 +152,7 @@ public Promise refetch() {
hasFetched = true;
resolve.onInvoke(this);
} else {
- CustomEventInit messageEvent = CustomEventInit.create();
- messageEvent.setDetail(new EventDetails(res.getData(), responseObjects));
- fireEvent(EVENT_MESSAGE, messageEvent);
+ fireEvent(EVENT_MESSAGE, new EventDetails(res.getData(), responseObjects));
}
});
messageStream.onStatus(status -> {
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/FigureSubscription.java b/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/FigureSubscription.java
index cd156e01a98..166d133aecf 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/FigureSubscription.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/FigureSubscription.java
@@ -3,7 +3,6 @@
//
package io.deephaven.web.client.api.widget.plot;
-import elemental2.dom.CustomEventInit;
import elemental2.promise.Promise;
import io.deephaven.web.client.api.DateWrapper;
import io.deephaven.web.client.api.JsTable;
@@ -82,25 +81,20 @@ public Set replaceSeries(final Set replacements) {
// For each of the series in copy, if this subscription is downsampled we need to notify of this fact.
if (downsampleAxisRange != null) {
- CustomEventInit init = CustomEventInit.create();
- init.setDetail(replacements.toArray());
- figure.fireEvent(JsFigure.EVENT_DOWNSAMPLESTARTED, init);
+ figure.fireEvent(JsFigure.EVENT_DOWNSAMPLESTARTED, replacements.toArray());
}
if (firstEventFired) {
// Next, if any data has loaded, regardless of downsample state, we need to fire an update event for those
// series
- CustomEventInit event = CustomEventInit.create();
- event.setDetail(new DataUpdateEvent(replacements.toArray(new JsSeries[0]), currentData, null));
- figure.fireEvent(JsFigure.EVENT_UPDATED, event);
+ figure.fireEvent(JsFigure.EVENT_UPDATED,
+ new DataUpdateEvent(replacements.toArray(new JsSeries[0]), currentData, null));
// Finally, if data was loaded and also the subscription is downsampled, we need to notify that the
// downsample
// is complete
if (downsampleAxisRange != null) {
- CustomEventInit successInit = CustomEventInit.create();
- successInit.setDetail(replacements.toArray());
- figure.fireEvent(JsFigure.EVENT_DOWNSAMPLEFINISHED, successInit);
+ figure.fireEvent(JsFigure.EVENT_DOWNSAMPLEFINISHED, replacements.toArray());
}
}
@@ -211,9 +205,7 @@ public void subscribe() {
} else {
zoomRange = null;
}
- CustomEventInit init = CustomEventInit.create();
- init.setDetail(includedSeries.toArray());
- figure.fireEvent(JsFigure.EVENT_DOWNSAMPLESTARTED, init);
+ figure.fireEvent(JsFigure.EVENT_DOWNSAMPLESTARTED, includedSeries.toArray());
Promise downsampled =
tablePromise.then(t -> t
.downsample(zoomRange, downsampleParams.getPixelCount(), downsampleAxisRange.getxCol(),
@@ -259,21 +251,18 @@ private Promise subscribe(final Promise tablePromise
sub.addEventListener(TableSubscription.EVENT_UPDATED, e -> {
// refire with specifics for the columns that we're watching here, after updating data arrays
AbstractTableSubscription.SubscriptionEventData subscriptionUpdateData =
- (AbstractTableSubscription.SubscriptionEventData) e.detail;
+ (AbstractTableSubscription.SubscriptionEventData) e.getDetail();
currentData.update(subscriptionUpdateData);
- CustomEventInit event = CustomEventInit.create();
- event.setDetail(new DataUpdateEvent(includedSeries.toArray(new JsSeries[0]), currentData,
- subscriptionUpdateData));
- figure.fireEvent(JsFigure.EVENT_UPDATED, event);
+ figure.fireEvent(JsFigure.EVENT_UPDATED,
+ new DataUpdateEvent(includedSeries.toArray(new JsSeries[0]), currentData,
+ subscriptionUpdateData));
if (!firstEventFired) {
firstEventFired = true;
if (downsampleAxisRange != null) {
- CustomEventInit successInit = CustomEventInit.create();
- successInit.setDetail(includedSeries.toArray());
- figure.fireEvent(JsFigure.EVENT_DOWNSAMPLEFINISHED, successInit);
+ figure.fireEvent(JsFigure.EVENT_DOWNSAMPLEFINISHED, includedSeries.toArray());
}
}
});
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/JsChart.java b/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/JsChart.java
index 989ecd8982d..51649f4d39b 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/JsChart.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/JsChart.java
@@ -7,7 +7,7 @@
import elemental2.core.JsArray;
import elemental2.core.JsObject;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.console_pb.figuredescriptor.ChartDescriptor;
-import io.deephaven.web.client.api.HasEventHandling;
+import io.deephaven.web.client.api.event.HasEventHandling;
import io.deephaven.web.client.api.widget.plot.enums.JsChartType;
import jsinterop.annotations.JsIgnore;
import jsinterop.annotations.JsNullable;
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/JsFigure.java b/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/JsFigure.java
index f16ea87f6fd..c3cd507f37c 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/JsFigure.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/JsFigure.java
@@ -5,7 +5,6 @@
import elemental2.core.JsArray;
import elemental2.core.JsObject;
-import elemental2.dom.CustomEventInit;
import elemental2.promise.Promise;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.console_pb.FigureDescriptor;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.console_pb.figuredescriptor.AxisDescriptor;
@@ -236,10 +235,8 @@ public Promise refetch() {
final FigureFetchError fetchError = new FigureFetchError(LazyPromise.ofObject(err),
this.descriptor != null ? this.descriptor.getErrorsList() : new JsArray<>());
// noinspection unchecked
- final CustomEventInit init = CustomEventInit.create();
- init.setDetail(fetchError);
unsuppressEvents();
- fireEvent(EVENT_RECONNECTFAILED, init);
+ fireEvent(EVENT_RECONNECTFAILED, fetchError);
suppressEvents();
// noinspection unchecked,rawtypes
@@ -269,10 +266,8 @@ public void reconnect() {
enqueueSubscriptionCheck();
return null;
}, failure -> {
- CustomEventInit init = CustomEventInit.create();
- init.setDetail(failure);
unsuppressEvents();
- fireEvent(EVENT_RECONNECTFAILED, init);
+ fireEvent(EVENT_RECONNECTFAILED, failure);
suppressEvents();
return null;
});
@@ -362,16 +357,14 @@ public void unsubscribe() {
@JsIgnore
public void downsampleNeeded(String message, Set series, double tableSize) {
- CustomEventInit failInit = CustomEventInit.create();
- failInit.setDetail(JsPropertyMap.of("series", series, "message", message, "size", tableSize));
- fireEvent(EVENT_DOWNSAMPLENEEDED, failInit);
+ fireEvent(EVENT_DOWNSAMPLENEEDED,
+ JsPropertyMap.of("series", series, "message", message, "size", tableSize));
}
@JsIgnore
public void downsampleFailed(String message, Set series, double tableSize) {
- CustomEventInit failInit = CustomEventInit.create();
- failInit.setDetail(JsPropertyMap.of("series", series, "message", message, "size", tableSize));
- fireEvent(EVENT_DOWNSAMPLEFAILED, failInit);
+ fireEvent(EVENT_DOWNSAMPLEFAILED,
+ JsPropertyMap.of("series", series, "message", message, "size", tableSize));
}
private void updateSubscriptions() {
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/JsFigureFactory.java b/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/JsFigureFactory.java
index 0b2dd4109ca..83360061f78 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/JsFigureFactory.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/JsFigureFactory.java
@@ -5,7 +5,6 @@
import com.vertispan.tsdefs.annotations.TsTypeRef;
import elemental2.core.JsArray;
-import elemental2.dom.CustomEventInit;
import elemental2.promise.Promise;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.console_pb.FigureDescriptor;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.console_pb.figuredescriptor.*;
@@ -82,9 +81,7 @@ private static Promise create(JsFigureDescriptor descriptor) {
figure.fireEvent(JsFigure.EVENT_RECONNECT);
figure.enqueueSubscriptionCheck();
} catch (JsFigure.FigureSourceException e) {
- final CustomEventInit init = CustomEventInit.create();
- init.setDetail(e);
- figure.fireEvent(JsFigure.EVENT_RECONNECTFAILED, init);
+ figure.fireEvent(JsFigure.EVENT_RECONNECTFAILED, e);
}
}));
removerFns
@@ -94,9 +91,7 @@ private static Promise create(JsFigureDescriptor descriptor) {
}
figure.unsubscribe();
- final CustomEventInit init = CustomEventInit.create();
- init.setDetail(err);
- figure.fireEvent(JsFigure.EVENT_RECONNECTFAILED, init);
+ figure.fireEvent(JsFigure.EVENT_RECONNECTFAILED, err);
}));
}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/JsMultiSeries.java b/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/JsMultiSeries.java
index 482bb9e281f..f377dc99e0c 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/JsMultiSeries.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/JsMultiSeries.java
@@ -6,12 +6,9 @@
import com.vertispan.tsdefs.annotations.TsInterface;
import com.vertispan.tsdefs.annotations.TsName;
import com.vertispan.tsdefs.annotations.TsTypeRef;
-import elemental2.dom.CustomEvent;
-import elemental2.dom.CustomEventInit;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.console_pb.figuredescriptor.*;
import io.deephaven.web.client.api.JsPartitionedTable;
import io.deephaven.web.client.api.widget.plot.enums.JsSeriesPlotStyle;
-import jsinterop.annotations.JsIgnore;
import jsinterop.annotations.JsProperty;
import java.util.Collections;
@@ -47,7 +44,7 @@ public void initSources(Map plotHandlesToPartitione
return null;
});
partitionedTable.addEventListener(JsPartitionedTable.EVENT_KEYADDED, event -> {
- requestTable(partitionedTable, ((CustomEvent) event).detail);
+ requestTable(partitionedTable, event.getDetail());
});
});
@@ -99,13 +96,10 @@ private void requestTable(JsPartitionedTable partitionedTable, Object key) {
series.setMultiSeries(this);
series.initSources(Collections.singletonMap(tableId, table), Collections.emptyMap());
- CustomEventInit init = CustomEventInit.create();
- init.setDetail(series);
-
parent.addSeriesFromMultiSeries(series);
- figure.fireEvent(JsFigure.EVENT_SERIES_ADDED, init);
- parent.fireEvent(JsChart.EVENT_SERIES_ADDED, init);
+ figure.fireEvent(JsFigure.EVENT_SERIES_ADDED, series);
+ parent.fireEvent(JsChart.EVENT_SERIES_ADDED, series);
return null;
});
}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/OneClick.java b/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/OneClick.java
index d95fa11614b..d1845fe88ce 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/OneClick.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/api/widget/plot/OneClick.java
@@ -5,10 +5,8 @@
import com.vertispan.tsdefs.annotations.TsInterface;
import com.vertispan.tsdefs.annotations.TsName;
-import com.vertispan.tsdefs.annotations.TsTypeRef;
import elemental2.core.JsArray;
import elemental2.core.JsMap;
-import elemental2.dom.CustomEventInit;
import elemental2.promise.Promise;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.console_pb.figuredescriptor.OneClickDescriptor;
import io.deephaven.web.client.api.Column;
@@ -193,9 +191,7 @@ private void fetchTable() {
if (table == null) {
// No table, no need to change the figure subscription, just trigger a
// synthetic event indicating no items
- CustomEventInit event = CustomEventInit.create();
- event.setDetail(DataUpdateEvent.empty(jsSeries));
- jsFigure.fireEvent(JsFigure.EVENT_UPDATED, event);
+ jsFigure.fireEvent(JsFigure.EVENT_UPDATED, DataUpdateEvent.empty(jsSeries));
} else {
// Subscribe to this key and wait for it...
currentTable = table;
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/ide/IdeClient.java b/web/client-api/src/main/java/io/deephaven/web/client/ide/IdeClient.java
deleted file mode 100644
index ce6a4f785f5..00000000000
--- a/web/client-api/src/main/java/io/deephaven/web/client/ide/IdeClient.java
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending
-//
-package io.deephaven.web.client.ide;
-
-import elemental2.promise.Promise;
-import io.deephaven.web.client.fu.CancellablePromise;
-import jsinterop.annotations.JsMethod;
-import jsinterop.annotations.JsType;
-
-/**
- */
-@JsType(name = "Ide", namespace = "dh")
-public class IdeClient {
- @Deprecated
- @JsMethod(name = "getExistingSession")
- public Promise getExistingSession_old(String websocketUrl, String authToken, String serviceId,
- String language) {
- return IdeClient.getExistingSession(websocketUrl, authToken, serviceId, language);
- }
-
- @Deprecated
- public static CancellablePromise getExistingSession(String websocketUrl, String authToken,
- String serviceId, String language) {
- IdeConnection ideConnection = new IdeConnection(websocketUrl, null, true);
- return ideConnection.startSession(language);
- }
-}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/ide/IdeConnection.java b/web/client-api/src/main/java/io/deephaven/web/client/ide/IdeConnection.java
index 7ea7d8a8ed1..5851fa1dbab 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/ide/IdeConnection.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/ide/IdeConnection.java
@@ -5,7 +5,6 @@
import com.vertispan.tsdefs.annotations.TsTypeRef;
import elemental2.core.JsArray;
-import elemental2.dom.CustomEventInit;
import elemental2.promise.Promise;
import io.deephaven.javascript.proto.dhinternal.browserheaders.BrowserHeaders;
import io.deephaven.javascript.proto.dhinternal.grpcweb.grpc.Code;
@@ -17,13 +16,10 @@
import io.deephaven.web.client.api.barrage.stream.ResponseStreamWrapper;
import io.deephaven.web.client.api.console.JsVariableChanges;
import io.deephaven.web.client.api.console.JsVariableDescriptor;
-import io.deephaven.web.client.fu.JsLog;
import io.deephaven.web.shared.data.ConnectToken;
import io.deephaven.web.shared.fu.JsConsumer;
import io.deephaven.web.shared.fu.JsRunnable;
-import jsinterop.annotations.JsConstructor;
import jsinterop.annotations.JsIgnore;
-import jsinterop.annotations.JsOptional;
import jsinterop.annotations.JsType;
import jsinterop.base.JsPropertyMap;
@@ -40,39 +36,26 @@ public class IdeConnection extends QueryConnectable {
public static final String EVENT_SHUTDOWN = "shutdown";
- private final JsRunnable deathListenerCleanup;
private final String serverUrl;
private final ConnectToken token = new ConnectToken();
private final ConnectOptions options;
/**
- * creates a new instance, from which console sessions can be made. options are optional.
+ * Creates a new instance, from which console sessions can be made.
*
* @param serverUrl The url used when connecting to the server. Read-only.
* @param connectOptions Optional Object
- * @param fromJava Optional boolean
*/
- @Deprecated
- @JsConstructor
- public IdeConnection(String serverUrl, @TsTypeRef(ConnectOptions.class) @JsOptional Object connectOptions,
- @JsOptional Boolean fromJava) {
+ public IdeConnection(String serverUrl, Object connectOptions) {
+ // Remove trailing slashes from the url
this.serverUrl = serverUrl.replaceAll("/+$", "");
- deathListenerCleanup = JsRunnable.doNothing();
if (connectOptions != null) {
options = new ConnectOptions(connectOptions);
} else {
options = new ConnectOptions();
}
-
- if (fromJava != Boolean.TRUE) {
- JsLog.warn(
- "dh.IdeConnection constructor is deprecated, please create a dh.CoreClient, call login(), then call getAsIdeConnection()");
- token.setType("Anonymous");
- token.setValue("");
- connection.get().whenServerReady("login").then(ignore -> Promise.resolve((Void) null));
- }
}
@Override
@@ -80,33 +63,24 @@ protected String logPrefix() {
return "IdeConnection on " + getServerUrl() + ": ";
}
- /**
- * Temporary method to split logic between IdeConnection and CoreClient
- */
@JsIgnore
+ @Override
public ConnectToken getToken() {
return token;
}
@JsIgnore
@Override
- public Promise getConnectToken() {
- return Promise.resolve(token);
- }
-
- @JsIgnore
- @Override
- public Promise getConnectOptions() {
- return Promise.resolve(options);
+ public ConnectOptions getOptions() {
+ return options;
}
/**
- * closes the current connection, releasing any resources on the server or client.
+ * Closes the current connection, releasing any resources on the server or client.
*/
+ // Made public to expose to JS
public void close() {
super.close();
-
- deathListenerCleanup.run();
}
/**
@@ -182,9 +156,7 @@ public void notifyServerShutdown(TerminationNotificationResponse success) {
}
// fire shutdown advice event
- CustomEventInit eventDetails = CustomEventInit.create();
- eventDetails.setDetail(details);
- fireEvent(EVENT_SHUTDOWN, eventDetails);
+ fireEvent(EVENT_SHUTDOWN, details);
// fire deprecated event
notifyConnectionError(new ResponseStreamWrapper.Status() {
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/ide/IdeSession.java b/web/client-api/src/main/java/io/deephaven/web/client/ide/IdeSession.java
index 438c5c857e4..2b7bf6b3a65 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/ide/IdeSession.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/ide/IdeSession.java
@@ -7,7 +7,6 @@
import com.vertispan.tsdefs.annotations.TsTypeRef;
import elemental2.core.JsArray;
import elemental2.core.JsSet;
-import elemental2.dom.CustomEventInit;
import elemental2.promise.Promise;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.ticket_pb.Ticket;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.console_pb.*;
@@ -18,6 +17,7 @@
import io.deephaven.web.client.api.console.JsVariableChanges;
import io.deephaven.web.client.api.console.JsVariableDescriptor;
import io.deephaven.web.client.api.console.JsVariableType;
+import io.deephaven.web.client.api.event.HasEventHandling;
import io.deephaven.web.client.api.tree.JsTreeTable;
import io.deephaven.web.client.api.widget.plot.JsFigure;
import io.deephaven.web.client.fu.CancellablePromise;
@@ -104,9 +104,7 @@ public IdeSession(
public Promise getTable(String name, @JsOptional Boolean applyPreviewColumns) {
return connection.getVariableDefinition(name, JsVariableType.TABLE).then(varDef -> {
final Promise table = connection.getTable(varDef, applyPreviewColumns);
- final CustomEventInit event = CustomEventInit.create();
- event.setDetail(table);
- fireEvent(EVENT_TABLE_OPENED, event);
+ fireEvent(EVENT_TABLE_OPENED, table);
return table;
});
}
@@ -149,9 +147,7 @@ public Promise> getObject(@TsTypeRef(JsVariableDescriptor.class) JsPropertyMap
public Promise newTable(String[] columnNames, String[] types, String[][] data, String userTimeZone) {
return connection.newTable(columnNames, types, data, userTimeZone, this).then(table -> {
- final CustomEventInit event = CustomEventInit.create();
- event.setDetail(table);
- fireEvent(EVENT_TABLE_OPENED, event);
+ fireEvent(EVENT_TABLE_OPENED, table);
return Promise.resolve(table);
});
@@ -165,9 +161,7 @@ public Promise newTable(String[] columnNames, String[] types, String[][
*/
public Promise mergeTables(JsTable[] tables) {
return connection.mergeTables(tables, this).then(table -> {
- final CustomEventInit event = CustomEventInit.create();
- event.setDetail(table);
- fireEvent(EVENT_TABLE_OPENED, event);
+ fireEvent(EVENT_TABLE_OPENED, table);
return Promise.resolve(table);
});
@@ -223,9 +217,7 @@ public CancellablePromise runCode(String code) {
});
CommandInfo commandInfo = new CommandInfo(code, result);
- final CustomEventInit event = CustomEventInit.create();
- event.setDetail(commandInfo);
- fireEvent(IdeSession.EVENT_COMMANDSTARTED, event);
+ fireEvent(IdeSession.EVENT_COMMANDSTARTED, commandInfo);
return result;
}
@@ -251,9 +243,7 @@ private BiDiStream ensureStream() {
});
currentStream.onStatus(status -> {
if (!status.isOk()) {
- CustomEventInit init = CustomEventInit.create();
- init.setDetail(status.getDetails());
- fireEvent(EVENT_REQUEST_FAILED, init);
+ fireEvent(EVENT_REQUEST_FAILED, status.getDetails());
pendingAutocompleteCalls.values().forEach(p -> {
p.fail("Connection error" + status.getDetails());
});
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/state/ClientTableState.java b/web/client-api/src/main/java/io/deephaven/web/client/state/ClientTableState.java
index 7eff8266775..2f3d92e36a9 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/state/ClientTableState.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/state/ClientTableState.java
@@ -16,6 +16,7 @@
import io.deephaven.web.client.api.barrage.def.ColumnDefinition;
import io.deephaven.web.client.api.barrage.def.InitialTableDefinition;
import io.deephaven.web.client.api.batch.TableConfig;
+import io.deephaven.web.client.api.event.HasEventHandling;
import io.deephaven.web.client.api.filter.FilterCondition;
import io.deephaven.web.client.api.lifecycle.HasLifecycle;
import io.deephaven.web.client.api.state.HasTableState;
@@ -914,7 +915,7 @@ public void cleanup() {
// notify any retainers who have events that we've been released.
for (Object retainer : JsItr.iterate(retainers.values())) {
if (retainer instanceof HasEventHandling) {
- ((HasEventHandling) retainer).fireEventWithDetail(HasEventHandling.INTERNAL_EVENT_RELEASED, this);
+ ((HasEventHandling) retainer).fireEvent(HasEventHandling.INTERNAL_EVENT_RELEASED, this);
}
}
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/state/HasTableBinding.java b/web/client-api/src/main/java/io/deephaven/web/client/state/HasTableBinding.java
index ba897fc54e9..0cc0a4e142c 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/state/HasTableBinding.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/state/HasTableBinding.java
@@ -3,7 +3,6 @@
//
package io.deephaven.web.client.state;
-import elemental2.dom.CustomEventInit;
import io.deephaven.web.client.api.TableTicket;
/**
@@ -26,7 +25,7 @@ public interface HasTableBinding {
void fireEvent(String name);
- void fireEvent(String name, CustomEventInit eventInit);
+ void fireEvent(String name, T detail);
void setState(ClientTableState appendTo);
diff --git a/web/client-api/src/main/java/io/deephaven/web/client/state/TableReviver.java b/web/client-api/src/main/java/io/deephaven/web/client/state/TableReviver.java
index 2f3220b476a..c6429ffff6c 100644
--- a/web/client-api/src/main/java/io/deephaven/web/client/state/TableReviver.java
+++ b/web/client-api/src/main/java/io/deephaven/web/client/state/TableReviver.java
@@ -5,7 +5,6 @@
import elemental2.core.JsArray;
import elemental2.core.JsMap;
-import elemental2.dom.CustomEventInit;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.ticket_pb.Ticket;
import io.deephaven.javascript.proto.dhinternal.browserheaders.BrowserHeaders;
import io.deephaven.javascript.proto.dhinternal.io.deephaven.proto.table_pb.BatchTableRequest;
@@ -175,15 +174,15 @@ public void fireEvent(String name) {
}
@Override
- public void fireEvent(String name, CustomEventInit e) {
+ public void fireEvent(String name, T detail) {
switch (name) {
case JsTable.EVENT_REQUEST_FAILED:
// log this failure
- JsLog.debug("Revivification failed", e.getDetail());
+ JsLog.debug("Revivification failed", detail);
//
return;
default:
- JsLog.debug("The table reviver does not accept event", name, e);
+ JsLog.debug("The table reviver does not accept event", name, detail);
}
}
diff --git a/web/client-api/src/test/java/io/deephaven/web/client/api/AbstractAsyncGwtTestCase.java b/web/client-api/src/test/java/io/deephaven/web/client/api/AbstractAsyncGwtTestCase.java
index 557f0ec2952..c674de47a4f 100644
--- a/web/client-api/src/test/java/io/deephaven/web/client/api/AbstractAsyncGwtTestCase.java
+++ b/web/client-api/src/test/java/io/deephaven/web/client/api/AbstractAsyncGwtTestCase.java
@@ -8,10 +8,11 @@
import elemental2.core.JsArray;
import elemental2.core.JsError;
import elemental2.core.JsString;
-import elemental2.dom.CustomEvent;
import elemental2.dom.DomGlobal;
import elemental2.promise.IThenable;
import elemental2.promise.Promise;
+import io.deephaven.web.client.api.event.Event;
+import io.deephaven.web.client.api.event.HasEventHandling;
import io.deephaven.web.client.api.subscription.ViewportData;
import io.deephaven.web.client.api.tree.JsTreeTable;
import io.deephaven.web.client.fu.CancellablePromise;
@@ -106,7 +107,7 @@ JsRunnable assertEventNotCalled(
final String ev = events[i];
undos[i] = handling.addEventListener(ev, e -> {
log("Did not expect", ev, "but fired event", e);
- report("Expected " + ev + " to not be called; detail: " + (e.detail));
+ report("Expected " + ev + " to not be called; detail: " + (e.getDetail()));
});
}
return () -> {
@@ -242,7 +243,7 @@ protected Promise assertUpdateReceived(JsTable table, int count, int ti
protected Promise assertUpdateReceived(JsTable table, Consumer check, int timeoutInMillis) {
return Promise.race(this.waitForEvent(table, JsTable.EVENT_UPDATED, e -> {
- ViewportData viewportData = e.detail;
+ ViewportData viewportData = e.getDetail();
check.accept(viewportData);
}, timeoutInMillis),
table.nextEvent(JsTable.EVENT_REQUEST_FAILED, (double) timeoutInMillis).then(Promise::reject))
@@ -274,7 +275,7 @@ protected IThenable.ThenOnFulfilledCallbackFn waitForTickTwice
}
protected Promise waitForEventWhere(V evented, String eventName,
- Predicate> check, int timeout) {
+ Predicate> check, int timeout) {
// note that this roughly reimplements the 'kill timer' so this can be run in parallel with itself or other
// similar steps
return new Promise<>((resolve, reject) -> {
@@ -309,7 +310,7 @@ protected Promise waitForEventWhere(V evented
}
protected Promise waitForEvent(V evented, String eventName,
- Consumer> check, int timeout) {
+ Consumer> check, int timeout) {
return this.waitForEventWhere(evented, eventName, e -> {
check.accept(e);
return true;
diff --git a/web/client-api/src/test/java/io/deephaven/web/client/api/HierarchicalTableTestGwt.java b/web/client-api/src/test/java/io/deephaven/web/client/api/HierarchicalTableTestGwt.java
index 0016db6133c..244e1fb1c29 100644
--- a/web/client-api/src/test/java/io/deephaven/web/client/api/HierarchicalTableTestGwt.java
+++ b/web/client-api/src/test/java/io/deephaven/web/client/api/HierarchicalTableTestGwt.java
@@ -4,9 +4,9 @@
package io.deephaven.web.client.api;
import elemental2.core.JsArray;
-import elemental2.dom.CustomEvent;
import elemental2.promise.Promise;
import io.deephaven.web.client.api.tree.JsRollupConfig;
+import io.deephaven.web.client.api.event.Event;
import io.deephaven.web.client.api.tree.JsTreeTable;
import io.deephaven.web.client.api.tree.TreeViewportData;
import io.deephaven.web.client.api.tree.enums.JsAggregationOperation;
@@ -60,8 +60,8 @@ public void testStaticTreeTable() {
return treeTable.nextEvent(
JsTreeTable.EVENT_UPDATED, 2001d);
}).then(event -> {
- assertEquals(10d, event.detail.getTreeSize());
- assertEquals(10, event.detail.getRows().length);
+ assertEquals(10d, event.getDetail().getTreeSize());
+ assertEquals(10, event.getDetail().getRows().length);
// move the viewport and try again
@@ -69,8 +69,8 @@ public void testStaticTreeTable() {
return treeTable.nextEvent(
JsTreeTable.EVENT_UPDATED, 2002d);
}).then(event -> {
- assertEquals(10d, event.detail.getTreeSize());
- assertEquals(5, event.detail.getRows().length);
+ assertEquals(10d, event.getDetail().getTreeSize());
+ assertEquals(5, event.getDetail().getRows().length);
treeTable.close();
@@ -101,9 +101,9 @@ public void testRefreshingTreeTable() {
// Wait for the table to tick such that the first row has children
// Read values from the one returned row
return waitForEventWhere(treeTable, JsTreeTable.EVENT_UPDATED,
- (CustomEvent d) -> d.detail
+ (Event d) -> d.getDetail()
.getTreeSize() == 1
- && d.detail.getRows().getAtAsAny(0).cast()
+ && d.getDetail().getRows().getAtAsAny(0).cast()
.hasChildren(),
10001)
.then(JsTreeTable::getViewportData)
@@ -133,7 +133,7 @@ public void testRefreshingTreeTable() {
// Wait for the expand to occur and table to show all 10 rows
return waitForEventWhere(treeTable, JsTreeTable.EVENT_UPDATED,
- (CustomEvent d) -> d.detail.getTreeSize() == 10,
+ (Event d) -> d.getDetail().getTreeSize() == 10,
14004);
})
.then(JsTreeTable::getViewportData)
@@ -160,8 +160,8 @@ public void testRefreshingTreeTable() {
return treeTable.nextEvent(
JsTreeTable.EVENT_UPDATED, 2002d);
}).then(event -> {
- assertEquals(10d, event.detail.getTreeSize());
- assertEquals(5, event.detail.getRows().length);
+ assertEquals(10d, event.getDetail().getTreeSize());
+ assertEquals(5, event.getDetail().getRows().length);
return Promise.resolve(treeTable);
})
@@ -195,7 +195,7 @@ public void testTickingRollup() {
// Wait for the table to tick such that we have at least 4 rows (root, three children)
return waitForEventWhere(rollup, JsTreeTable.EVENT_UPDATED,
- (CustomEvent d) -> d.detail.getTreeSize() == 4,
+ (Event d) -> d.getDetail().getTreeSize() == 4,
10002)
.then(JsTreeTable::getViewportData)
.then(data -> Promise.resolve((TreeViewportData) data))
@@ -240,7 +240,7 @@ public void testTickingRollup() {
// Wait for the expand to occur and table to show all 10 rows
return waitForEventWhere(rollup, JsTreeTable.EVENT_UPDATED,
- (CustomEvent d) -> d.detail.getTreeSize() > 4,
+ (Event d) -> d.getDetail().getTreeSize() > 4,
14008);
})
.then(JsTreeTable::getViewportData)
@@ -267,7 +267,7 @@ public void testTickingRollup() {
// Collapse row 2, wait until back to 4 rows
rollup.collapse(JsTreeTable.RowReferenceUnion.of(1));
return waitForEventWhere(rollup, JsTreeTable.EVENT_UPDATED,
- (CustomEvent d) -> d.detail.getTreeSize() == 4,
+ (Event d) -> d.getDetail().getTreeSize() == 4,
14009);
})
.then(event -> {
@@ -313,7 +313,7 @@ public void testCreateRollup() {
delayTestFinish(15000 + step);
return waitForEventWhere(r, JsTreeTable.EVENT_UPDATED,
- (CustomEvent d) -> r.getSize() == 4, 13000 + step)
+ (Event d) -> r.getSize() == 4, 13000 + step)
.then(event -> Promise.resolve(r));
}));
}
diff --git a/web/client-api/src/test/java/io/deephaven/web/client/api/PartitionedTableTestGwt.java b/web/client-api/src/test/java/io/deephaven/web/client/api/PartitionedTableTestGwt.java
index d0b9c4fcc40..9bd0b9446a2 100644
--- a/web/client-api/src/test/java/io/deephaven/web/client/api/PartitionedTableTestGwt.java
+++ b/web/client-api/src/test/java/io/deephaven/web/client/api/PartitionedTableTestGwt.java
@@ -4,7 +4,7 @@
package io.deephaven.web.client.api;
import elemental2.core.JsArray;
-import elemental2.dom.CustomEvent;
+import io.deephaven.web.client.api.event.Event;
public class PartitionedTableTestGwt extends AbstractAsyncGwtTestCase {
@Override
@@ -112,7 +112,7 @@ public void testTickingPartitionedTable() {
assertEquals("x", columns[2].getName());
return waitForEventWhere(partitionedTable, JsPartitionedTable.EVENT_KEYADDED,
- (CustomEvent> e) -> e.detail.getAt(0).equals("2"), 14004)
+ (Event> e) -> e.getDetail().getAt(0).equals("2"), 14004)
.then(event -> partitionedTable.getTable("2")).then(constituentTable -> {
assertEquals(3, constituentTable.getColumns().length);
assertTrue(constituentTable.getSize() >= 2);
@@ -141,7 +141,7 @@ public void testTickingTransformedPartitionedTable() {
assertEquals("x", columns[1].getName());
return waitForEventWhere(partitionedTable, JsPartitionedTable.EVENT_KEYADDED,
- (CustomEvent> e) -> e.detail.getAt(0).equals("2"), 14005)
+ (Event> e) -> e.getDetail().getAt(0).equals("2"), 14005)
.then(event -> partitionedTable.getTable("2")).then(constituentTable -> {
assertEquals(2, constituentTable.getColumns().length);
assertTrue(constituentTable.getSize() >= 1);
diff --git a/web/client-api/src/test/java/io/deephaven/web/client/api/TotalsTableTestGwt.java b/web/client-api/src/test/java/io/deephaven/web/client/api/TotalsTableTestGwt.java
index 857cad855c5..baeaf723cfb 100644
--- a/web/client-api/src/test/java/io/deephaven/web/client/api/TotalsTableTestGwt.java
+++ b/web/client-api/src/test/java/io/deephaven/web/client/api/TotalsTableTestGwt.java
@@ -5,9 +5,9 @@
import elemental2.core.JsArray;
import elemental2.core.JsString;
-import elemental2.dom.CustomEvent;
import elemental2.promise.IThenable;
import elemental2.promise.Promise;
+import io.deephaven.web.client.api.event.Event;
import io.deephaven.web.client.api.filter.FilterCondition;
import io.deephaven.web.client.api.filter.FilterValue;
import io.deephaven.web.client.api.subscription.ViewportData;
@@ -331,7 +331,7 @@ public void testGroupedTotals() {
// confirm the grand totals are unchanged
return waitForEvent(totals, JsTable.EVENT_UPDATED, update -> {
- ViewportData viewportData = (ViewportData) update.detail;
+ ViewportData viewportData = (ViewportData) update.getDetail();
// 2 rows (one for k=0, one for k=1)
assertEquals(2, viewportData.getRows().length);
@@ -389,7 +389,7 @@ static TotalsResults of(int k, long i, double avg, double min) {
}
}
- private Consumer checkTotals(
+ private Consumer> checkTotals(
JsTotalsTable totals,
long i,
double avg,
@@ -397,7 +397,7 @@ private Consumer checkTotals(
String messages) {
String ext = messages;
return update -> {
- ViewportData viewportData = (ViewportData) update.detail;
+ ViewportData viewportData = update.getDetail();
assertEquals(1, viewportData.getRows().length);
assertEquals(3, viewportData.getColumns().length);
@@ -412,13 +412,13 @@ private Consumer checkTotals(
};
}
- private Consumer checkTotals(
+ private Consumer> checkTotals(
JsTotalsTable totals,
String messages,
TotalsResults... expected) {
String ext = messages;
return update -> {
- ViewportData viewportData = (ViewportData) update.detail;
+ ViewportData viewportData = update.getDetail();
assertEquals("Viewport data rows", expected.length, viewportData.getRows().length);
assertEquals("Viewport columns", 4, viewportData.getColumns().length);
@@ -442,9 +442,9 @@ private Consumer checkTotals(
* Specialized waitForEvent since JsTotalsTable isn't a HasEventHandling subtype, and doesnt make sense to shoehorn
* it in just for tests.
*/
- private Promise waitForEvent(JsTotalsTable table, String eventName, Consumer check,
+ private Promise waitForEvent(JsTotalsTable table, String eventName, Consumer> check,
int timeout) {
- return waitForEvent(table.getWrappedTable(), eventName, check::accept, timeout)
+ return waitForEvent(table.getWrappedTable(), eventName, check, timeout)
.then(t -> Promise.resolve(table));
}
diff --git a/web/client-api/src/test/java/io/deephaven/web/client/api/subscription/ViewportTestGwt.java b/web/client-api/src/test/java/io/deephaven/web/client/api/subscription/ViewportTestGwt.java
index 4feb544df3d..0d89e2c7917 100644
--- a/web/client-api/src/test/java/io/deephaven/web/client/api/subscription/ViewportTestGwt.java
+++ b/web/client-api/src/test/java/io/deephaven/web/client/api/subscription/ViewportTestGwt.java
@@ -4,7 +4,6 @@
package io.deephaven.web.client.api.subscription;
import elemental2.core.JsArray;
-import elemental2.dom.CustomEvent;
import elemental2.dom.DomGlobal;
import elemental2.promise.IThenable;
import elemental2.promise.Promise;
@@ -12,10 +11,11 @@
import io.deephaven.web.client.api.Column;
import io.deephaven.web.client.api.DateWrapper;
import io.deephaven.web.client.api.Format;
-import io.deephaven.web.client.api.HasEventHandling;
import io.deephaven.web.client.api.JsRangeSet;
import io.deephaven.web.client.api.JsTable;
import io.deephaven.web.client.api.TableData;
+import io.deephaven.web.client.api.event.Event;
+import io.deephaven.web.client.api.event.HasEventHandling;
import io.deephaven.web.client.api.filter.FilterCondition;
import io.deephaven.web.client.api.filter.FilterValue;
import io.deephaven.web.shared.fu.RemoverFn;
@@ -538,8 +538,8 @@ private IThenable helperForViewportWithNoInitialItems(JsTable t, Column
.then(table -> {
// wait for the next tick, where we get the "first" row added, confirm that the viewport
// data is sane
- return waitForEventWhere(table, "updated", (CustomEvent e) -> {
- ViewportData viewport = e.detail;
+ return waitForEventWhere(table, "updated", (Event e) -> {
+ ViewportData viewport = e.getDetail();
if (viewport.getRows().length != 1) {
return false; // wrong data, wait for another event
}
@@ -553,8 +553,8 @@ private IThenable helperForViewportWithNoInitialItems(JsTable t, Column
})
.then(table -> {
// again wait for the table to go back to zero items, make sure it makes sense
- return waitForEventWhere(table, "updated", (CustomEvent e) -> {
- ViewportData emptyViewport = (ViewportData) e.detail;
+ return waitForEventWhere(table, "updated", (Event e) -> {
+ ViewportData emptyViewport = e.getDetail();
if (emptyViewport.getRows().length != 0) {
return false; // wrong data, wait for another event
}
@@ -564,8 +564,8 @@ private IThenable helperForViewportWithNoInitialItems(JsTable t, Column
})
.then(table -> {
// one more tick later, we'll see the item back again
- return waitForEventWhere(table, "updated", (CustomEvent e) -> {
- ViewportData viewport = (ViewportData) e.detail;
+ return waitForEventWhere(table, "updated", (Event e) -> {
+ ViewportData viewport = e.getDetail();
if (viewport.getRows().length != 1) {
return false; // wrong data, wait for another event
}