2 * Copyright (c) 2014, 2019 The xterm.js authors. All rights reserved.
5 * Implements the attach method, that attaches the terminal to a WebSocket stream.
8 import { Terminal, IDisposable, ITerminalAddon } from 'xterm';
10 interface IAttachOptions {
11 bidirectional?: boolean;
14 export class AttachAddon implements ITerminalAddon {
15 private _socket: WebSocket;
16 private _bidirectional: boolean;
17 private _disposables: IDisposable[] = [];
19 constructor(socket: WebSocket, options?: IAttachOptions) {
20 this._socket = socket;
21 // always set binary type to arraybuffer, we do not handle blobs
22 this._socket.binaryType = 'arraybuffer';
23 this._bidirectional = (options && options.bidirectional === false) ? false : true;
26 public activate(terminal: Terminal): void {
27 this._disposables.push(
28 addSocketListener(this._socket, 'message', ev => {
29 const data: ArrayBuffer | string = ev.data;
30 terminal.write(typeof data === 'string' ? data : new Uint8Array(data));
34 if (this._bidirectional) {
35 this._disposables.push(terminal.onData(data => this._sendData(data)));
38 this._disposables.push(addSocketListener(this._socket, 'close', () => this.dispose()));
39 this._disposables.push(addSocketListener(this._socket, 'error', () => this.dispose()));
42 public dispose(): void {
43 this._disposables.forEach(d => d.dispose());
46 private _sendData(data: string): void {
47 // TODO: do something better than just swallowing
48 // the data if the socket is not in a working condition
49 if (this._socket.readyState !== 1) {
52 this._socket.send(data);
56 function addSocketListener<K extends keyof WebSocketEventMap>(socket: WebSocket, type: K, handler: (this: WebSocket, ev: WebSocketEventMap[K]) => any): IDisposable {
57 socket.addEventListener(type, handler);
64 socket.removeEventListener(type, handler);