@eclipse-glsp/theia-integration
Version:
Glue code to integrate GLSP clients into Eclipse Theia
92 lines • 3.97 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebSocketConnectionForwarder = void 0;
exports.wrapWebSocket = wrapWebSocket;
/********************************************************************************
* Copyright (c) 2023-2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
const protocol_1 = require("@eclipse-glsp/protocol");
const core_1 = require("@theia/core");
/**
* Creates a new vscode-jsonrpc {@link MessageConnection} on top of a given WebSocket.
* It handles messages between then service client channel and the given WebSocket.
*/
class WebSocketConnectionForwarder {
constructor(clientChannel, webSocket) {
this.clientChannel = clientChannel;
this.webSocket = webSocket;
this.toDispose = new core_1.DisposableCollection();
this.initialBufferStore = [];
/**
* The webSocket connection is successfully established `onOpen`
* The service client channel however, might send message (i.e. the InitializeRequest) once the backend contribution is resolved.
* In this case, the listener could not yet be successfully registered, hence we buffer such messages and process them,
* once the webSocket connection was successfully established.
*/
this.initialChannelListener = this.clientChannel.onMessage(msgProvider => {
const buffer = msgProvider().readBytes();
this.initialBufferStore.push(buffer);
});
webSocket.onopen = () => {
this.initialize(webSocket);
};
}
initialize(webSocket) {
const wrappedWebSocket = wrapWebSocket(webSocket);
const connection = (0, protocol_1.createWebSocketConnection)(wrappedWebSocket);
connection.listen();
this.toDispose.pushAll([
connection.onClose(() => webSocket.close()),
this.clientChannel.onMessage(msgProvider => {
const buffer = msgProvider().readBytes();
wrappedWebSocket.send(this.decodeMessage(buffer));
}),
connection.onClose(() => this.clientChannel.close()),
core_1.Disposable.create(() => {
this.clientChannel.close();
connection.dispose();
})
]);
webSocket.on('message', msg => {
this.clientChannel
.getWriteBuffer()
.writeBytes(msg)
.commit();
});
// process initially received buffer messages
this.initialChannelListener.dispose();
this.initialBufferStore.forEach(msg => {
wrappedWebSocket.send(this.decodeMessage(msg));
});
this.initialBufferStore = [];
}
decodeMessage(buffer) {
return new TextDecoder().decode(buffer);
}
dispose() {
this.toDispose.dispose();
}
}
exports.WebSocketConnectionForwarder = WebSocketConnectionForwarder;
function wrapWebSocket(socket) {
return {
send: content => socket.send(content),
onMessage: cb => socket.on('message', cb),
onClose: cb => socket.on('close', cb),
onError: cb => socket.on('error', cb),
dispose: () => socket.close()
};
}
//# sourceMappingURL=websocket-connection-forwarder.js.map