// ==UserScript== // @name Websocket debugger // @namespace thomas-rosenau.de // @version 1 // @grant none // @include * // @run-at document-start // ==/UserScript== ((main) => { if (window === window.top) { // http://stackoverflow.com/a/5006952/27862 let script = document.createElement('script'); script.textContent = `try{(${main})();}catch(e){console.log(e);}`; if (!document.head) { return; } document.head.appendChild(script).parentNode.removeChild(script); } })(() => { let log = (color, i, key, ...args) => { switch(key) { case 'onmessage': console.log(`%c[WS${i}]%c↓%c${args[0].data}`, `float: left; color: ${color};`, 'font-size: 120%; float: left', 'word-break: break-all; font-size: 110%; float: left; margin: 0 .5em; font-family: Arial, sans-serif; padding: .5em; background: #f4f8f6; border-radius: .5em; box-shadow: 0 1px 1px gray'); break; case 'send': console.log(`%c[WS${i}]%c↑%c${args[0]}`, `float: left; color: ${color};`, 'font-size: 120%; float: left', 'word-break: break-all; font-size: 110%; float: right; margin: 0 .5em 0 4em; font-family: Arial, sans-serif; padding: .5em; background: rgba(224, 251, 199); border-radius: .5em; box-shadow: 0 1px 1px gray'); break; case 'onclose': console.log(`%c[WS${i}]%c close ${args[0] ? args[0].target.url : ''}`, `float: left; color: ${color};`); break; default: console.log(`%c[WS${i}]%c`, `color: ${color};`, '', key.replace(/^on/, ''), ...args); } }; const events = ['onclose', 'onerror', 'onmessage', 'onopen']; let i = 0; let construct = (WebSocket, args) => { let clog = log.bind(null, `hsl(${300 + 135 * i}, 70%, 50%)`); i ++; clog(i, 'new', ...args); let handler = ((i) => ({ get(connection, prop) { if (typeof connection[prop] === 'function') { return (...args) => { clog(i, prop, ...args); return connection[prop](...args); }; } return connection[prop]; }, set(connection, prop, handler) { let value = handler; if (events.includes(prop)) { value = (...args) => { clog(i, prop, ...args); return handler(...args); }; } connection[prop] = value; return true; }, deleteProperty(connection, prop) { if (events.includes(prop)) { connection[prop] = clog.bind(null, i, prop); } else { delete connection[prop]; } } }))(i); let result = new Proxy(new WebSocket(...args), handler); events.forEach(evt => delete result[evt]); // init logging return result; }; window.WebSocket = new Proxy(WebSocket, {construct}); });