]> git.proxmox.com Git - mirror_novnc.git/blobdiff - core/websock.js
Avoid big strings on the stack
[mirror_novnc.git] / core / websock.js
index 78809a1ac63eb1ed2486106fdfea1a47d416f4ba..6b0336157bb17ca7f806dbf999abd440bb654e9f 100644 (file)
@@ -14,9 +14,6 @@
 
 import * as Log from './util/logging.js';
 
-/*jslint browser: true, bitwise: true */
-/*global Util*/
-
 export default function Websock() {
     "use strict";
 
@@ -40,29 +37,14 @@ export default function Websock() {
         '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
@@ -118,9 +100,14 @@ Websock.prototype = {
 
     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) {
@@ -152,7 +139,7 @@ Websock.prototype = {
     // 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) {
@@ -168,10 +155,6 @@ Websock.prototype = {
     // 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;
@@ -211,7 +194,6 @@ Websock.prototype = {
     },
 
     open: function (uri, protocols) {
-        var ws_schema = uri.match(/^([a-z]+):\/\//)[1];
         this.init();
 
         this._websocket = new WebSocket(uri, protocols);
@@ -259,7 +241,7 @@ Websock.prototype = {
     },
 
     _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
@@ -274,12 +256,12 @@ Websock.prototype = {
         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));
@@ -297,7 +279,7 @@ Websock.prototype = {
 
     _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);
         }
@@ -306,46 +288,18 @@ Websock.prototype = {
     },
 
     _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");
         }
     }
 };