import * as Log from './util/logging.js';
-/*jslint browser: true, bitwise: true */
-/*global Util*/
-
export default function Websock() {
"use strict";
'close': function () {},
'error': function () {}
};
-};
+}
// this has performance issues in some versions Chromium, and
// doesn't gain a tremendous amount of performance increase in Firefox
// at the moment. It may be valuable to turn it on in the future.
-var ENABLE_COPYWITHIN = false;
-
-var MAX_RQ_GROW_SIZE = 40 * 1024 * 1024; // 40 MiB
-
-var typedArrayToString = (function () {
- // This is only for PhantomJS, which doesn't like apply-ing
- // with Typed Arrays
- try {
- var arr = new Uint8Array([1, 2, 3]);
- String.fromCharCode.apply(null, arr);
- return function (a) { return String.fromCharCode.apply(null, a); };
- } catch (ex) {
- return function (a) {
- return String.fromCharCode.apply(
- null, Array.prototype.slice.call(a));
- };
- }
-})();
+const ENABLE_COPYWITHIN = false;
+
+const MAX_RQ_GROW_SIZE = 40 * 1024 * 1024; // 40 MiB
Websock.prototype = {
// Getters and Setters
rQshiftStr: function (len) {
if (typeof(len) === 'undefined') { len = this.rQlen(); }
- var arr = new Uint8Array(this._rQ.buffer, this._rQi, len);
- this._rQi += len;
- return typedArrayToString(arr);
+ const arr = this.rQshiftBytes(len);
+ let str = "";
+ // Handle large arrays in steps to avoid long strings on the stack
+ for (let i = 0; i < len; i += 4096) {
+ let part = arr.slice(i, i + Math.min(4096, len));
+ str = str.concat(String.fromCharCode.apply(null, part));
+ }
+ return str;
},
rQshiftBytes: function (len) {
// to be available in the receive queue. Return true if we need to
// wait (and possibly print a debug message), otherwise false.
rQwait: function (msg, num, goback) {
- var rQlen = this._rQlen - this._rQi; // Skip rQlen() function call
+ const rQlen = this._rQlen - this._rQi; // Skip rQlen() function call
if (rQlen < num) {
if (goback) {
if (this._rQi < goback) {
// Send Queue
flush: function () {
- if (this._websocket.bufferedAmount !== 0) {
- Log.Debug("bufferedAmount: " + this._websocket.bufferedAmount);
- }
-
if (this._sQlen > 0 && this._websocket.readyState === WebSocket.OPEN) {
this._websocket.send(this._encode_message());
this._sQlen = 0;
},
open: function (uri, protocols) {
- var ws_schema = uri.match(/^([a-z]+):\/\//)[1];
this.init();
this._websocket = new WebSocket(uri, protocols);
},
_expand_compact_rQ: function (min_fit) {
- var resizeNeeded = min_fit || this._rQlen - this._rQi > this._rQbufferSize / 2;
+ const resizeNeeded = min_fit || this._rQlen - this._rQi > this._rQbufferSize / 2;
if (resizeNeeded) {
if (!min_fit) {
// just double the size if we need to do compaction
if (this._rQbufferSize > MAX_RQ_GROW_SIZE) {
this._rQbufferSize = MAX_RQ_GROW_SIZE;
if (this._rQbufferSize - this._rQlen - this._rQi < min_fit) {
- throw new Exception("Receive Queue buffer exceeded " + MAX_RQ_GROW_SIZE + " bytes, and the new message could not fit");
+ throw new Error("Receive Queue buffer exceeded " + MAX_RQ_GROW_SIZE + " bytes, and the new message could not fit");
}
}
if (resizeNeeded) {
- var old_rQbuffer = this._rQ.buffer;
+ const old_rQbuffer = this._rQ.buffer;
this._rQmax = this._rQbufferSize / 8;
this._rQ = new Uint8Array(this._rQbufferSize);
this._rQ.set(new Uint8Array(old_rQbuffer, this._rQi));
_decode_message: function (data) {
// push arraybuffer values onto the end
- var u8 = new Uint8Array(data);
+ const u8 = new Uint8Array(data);
if (u8.length > this._rQbufferSize - this._rQlen) {
this._expand_compact_rQ(u8.length);
}
},
_recv_message: function (e) {
- try {
- this._decode_message(e.data);
- if (this.rQlen() > 0) {
- this._eventHandlers.message();
- // Compact the receive queue
- if (this._rQlen == this._rQi) {
- this._rQlen = 0;
- this._rQi = 0;
- } else if (this._rQlen > this._rQmax) {
- this._expand_compact_rQ();
- }
- } else {
- Log.Debug("Ignoring empty message");
- }
- } catch (exc) {
- var exception_str = "";
- if (exc.name) {
- exception_str += "\n name: " + exc.name + "\n";
- exception_str += " message: " + exc.message + "\n";
- }
-
- if (typeof exc.description !== 'undefined') {
- exception_str += " description: " + exc.description + "\n";
- }
-
- if (typeof exc.stack !== 'undefined') {
- exception_str += exc.stack;
- }
-
- if (exception_str.length > 0) {
- Log.Error("recv_message, caught exception: " + exception_str);
- } else {
- Log.Error("recv_message, caught exception: " + exc);
- }
-
- if (typeof exc.name !== 'undefined') {
- this._eventHandlers.error(exc.name + ": " + exc.message);
- } else {
- this._eventHandlers.error(exc);
+ this._decode_message(e.data);
+ if (this.rQlen() > 0) {
+ this._eventHandlers.message();
+ // Compact the receive queue
+ if (this._rQlen == this._rQi) {
+ this._rQlen = 0;
+ this._rQi = 0;
+ } else if (this._rQlen > this._rQmax) {
+ this._expand_compact_rQ();
}
+ } else {
+ Log.Debug("Ignoring empty message");
}
}
};