class Conn { constructor(id) { this.id = id; this.conn = null; this.q = []; this.onstatechange = () => {} this.onmessage = () => {}; this.createConn(); setInterval(() => this.send({ type: "ping" }), 30000); } createConn() { this.conn = new WebSocket(`${location.protocol.replace("http", "ws")}//${location.host}`); this.onstatechange("Connecting"); this.connected = false; this.ready = false; this.conn.onclose = evt => { this.conn = null; this.onstatechange(`Closed: ${evt.code}`); setTimeout(this.createConn.bind(this), 2000); } this.conn.onopen = () => { this.onstatechange("Identifying"); this.conn.send(JSON.stringify({ type: "identify-master", id: this.id })); this.q.forEach(el => this.conn.send(el)); this.q = []; } this.conn.onmessage = msg => { console.log(msg.data); let obj = JSON.parse(msg.data); switch (obj.type) { case "identify-response": if (obj.err == null) { this.connected = true; this.onstatechange("Waiting for target"); } else { this.onstatechange(`Error: ${obj.err}`); } break; case "target-connect": this.ready = true; this.onstatechange("Ready"); break; case "target-disconnect": this.ready = false; this.onstatechange("Waiting for target"); break; case "js-result": this.onjsresult(obj.err, obj.result); break; case "log": this.onlog(obj.log); break; case "pong": break; default: console.warn("Unknown message type:", obj.type); } } } runJavascript(js) { this.send({ type: "run-js", js }); } send(obj) { if (this.connected) this.conn.send(JSON.stringify(obj)); } }