THRIFT-5003: Websocket Connection in Browsers with nodejs code

* changed this to self in forEach callback

* updated minimum node version to 8.16.2 (Maintenance LTS until December 2019)
changed ws_connection.js to work in the browser, with isomorphic-ws
added exports for `wsConnection`, `createWSConnection`, `createWSClient`

* added exports for WSConnection to browser.js

* extended the sample of nodejs code in the browser with webpack

* tested and updated node version to LTS 10.18.0 Dubnium
discussion based: https://github.com/apache/thrift/pull/1927#discussion_r358140463
diff --git a/lib/nodejs/README.md b/lib/nodejs/README.md
index ed306c1..c087440 100644
--- a/lib/nodejs/README.md
+++ b/lib/nodejs/README.md
@@ -75,8 +75,8 @@
 
 thrift --gen js:node,ts,es6,with_ns
 
-```
-import * as thrift from 'thrift/browser';
+```javascript
+import * as thrift from 'thrift';
 import { MyServiceClient } from '../gen-nodejs/MyService';
 
 let host = window.location.hostname;
@@ -108,4 +108,35 @@
   });
 ```
 
-Note that thrift/index.js must be renamed or skipped for browsers.
+Bundlers, like webpack, will use thrift/browser.js by default because of the 
+`"browser": "./lib/nodejs/lib/thrift/browser.js"` field in package.json.
+
+### Browser example with WebSocket, BufferedTransport and BinaryProtocol
+```javascript
+import thrift from 'thrift';
+import { MyServiceClient } from '../gen-nodejs/MyService';
+
+const host = window.location.hostname;
+const port = 9090;
+const opts = {
+  transport: thrift.TBufferedTransport,
+  protocol: thrift.TBinaryProtocol
+}
+const connection = thrift.createWSConnection(host, port, opts);
+connection.open();
+const thriftClient = thrift.createWSClient(MyServiceClient, connection);
+
+connection.on('error', (err) => {
+  console.error(err);
+});
+
+thriftClient.myService(param)
+  .then((result) => {
+    console.log(result);
+  })
+  .catch((err) => {
+    ....
+  });
+```
+
+
diff --git a/lib/nodejs/lib/thrift/browser.js b/lib/nodejs/lib/thrift/browser.js
index 67ce853..82e5469 100644
--- a/lib/nodejs/lib/thrift/browser.js
+++ b/lib/nodejs/lib/thrift/browser.js
@@ -23,6 +23,11 @@
 exports.createXHRConnection = xhrConnection.createXHRConnection;
 exports.createXHRClient = xhrConnection.createXHRClient;
 
+var wsConnection = require('./ws_connection');
+exports.WSConnection = wsConnection.WSConnection;
+exports.createWSConnection = wsConnection.createWSConnection;
+exports.createWSClient = wsConnection.createWSClient;
+
 exports.Multiplexer = require('./multiplexed_protocol').Multiplexer;
 
 exports.TWebSocketTransport = require('./ws_transport');
diff --git a/lib/nodejs/lib/thrift/ws_connection.js b/lib/nodejs/lib/thrift/ws_connection.js
index 052cbd4..8ee8f6e 100644
--- a/lib/nodejs/lib/thrift/ws_connection.js
+++ b/lib/nodejs/lib/thrift/ws_connection.js
@@ -17,18 +17,16 @@
  * under the License.
  */
 var util = require('util');
-var WebSocket = require('ws');
+var WebSocket = require('isomorphic-ws');
 var EventEmitter = require("events").EventEmitter;
 var thrift = require('./thrift');
-var ttransport = require('./transport');
-var tprotocol = require('./protocol');
 
 var TBufferedTransport = require('./buffered_transport');
 var TJSONProtocol = require('./json_protocol');
 var InputBufferUnderrunError = require('./input_buffer_underrun_error');
 
 var createClient = require('./create_client');
-
+var jsEnv = require('browser-or-node');
 exports.WSConnection = WSConnection;
 
 /**
@@ -69,7 +67,7 @@
  * @throws {error} Exceptions other than ttransport.InputBufferUnderrunError are rethrown
  * @event {error} The "error" event is fired when a Node.js error event occurs during
  *     request or response processing, in which case the node error is passed on. An "error"
- *     event may also be fired when the connectison can not map a response back to the
+ *     event may also be fired when the connection can not map a response back to the
  *     appropriate client (an internal error), generating a TApplicationException.
  * @classdesc WSConnection objects provide Thrift end point transport
  *     semantics implemented using Websockets.
@@ -80,7 +78,6 @@
   EventEmitter.call(this);
 
   //Set configuration
-  var self = this;
   this.options = options || {};
   this.host = host;
   this.port = port;
@@ -113,14 +110,13 @@
 };
 
 WSConnection.prototype.__onOpen = function() {
-  var self = this;
   this.emit("open");
   if (this.send_pending.length > 0) {
     //If the user made calls before the connection was fully
     //open, send them now
     this.send_pending.forEach(function(data) {
-      self.socket.send(data);
-    });
+      this.socket.send(data);
+    }, this);
     this.send_pending = [];
   }
 };
@@ -184,7 +180,7 @@
 };
 
 WSConnection.prototype.__onData = function(data) {
-  if (Object.prototype.toString.call(data) == "[object ArrayBuffer]") {
+  if (Object.prototype.toString.call(data) === "[object ArrayBuffer]") {
     data = new Uint8Array(data);
   }
   var buf = new Buffer(data);
@@ -207,7 +203,7 @@
  * @returns {boolean}
  */
 WSConnection.prototype.isOpen = function() {
-  return this.socket && this.socket.readyState == this.socket.OPEN;
+  return this.socket && this.socket.readyState === this.socket.OPEN;
 };
 
 /**
@@ -215,11 +211,15 @@
  */
 WSConnection.prototype.open = function() {
   //If OPEN/CONNECTING/CLOSING ignore additional opens
-  if (this.socket && this.socket.readyState != this.socket.CLOSED) {
+  if (this.socket && this.socket.readyState !== this.socket.CLOSED) {
     return;
   }
   //If there is no socket or the socket is closed:
-  this.socket = new WebSocket(this.uri(), "", this.wsOptions);
+  if (jsEnv.isBrowser) {
+    this.socket = new WebSocket(this.uri());
+  } else {
+    this.socket = new WebSocket(this.uri(), "", this.wsOptions);
+  }
   this.socket.binaryType = 'arraybuffer';
   this.socket.onopen = this.__onOpen.bind(this);
   this.socket.onmessage = this.__onMessage.bind(this);
@@ -245,8 +245,8 @@
   var host = this.host;
 
   // avoid port if default for schema
-  if (this.port && (('wss' == schema && this.port != 443) ||
-    ('ws' == schema && this.port != 80))) {
+  if (this.port && (('wss' === schema && this.port !== 443) ||
+    ('ws' === schema && this.port !== 80))) {
     port = ':' + this.port;
   }
 
diff --git a/package-lock.json b/package-lock.json
index e88fb1e..15a1885 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -24,6 +24,12 @@
         "js-tokens": "^4.0.0"
       }
     },
+    "@babel/parser": {
+      "version": "7.7.3",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.3.tgz",
+      "integrity": "sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A==",
+      "dev": true
+    },
     "@types/node": {
       "version": "10.12.6",
       "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.6.tgz",
@@ -171,9 +177,9 @@
       "dev": true
     },
     "async-limiter": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
-      "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+      "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
     },
     "asynckit": {
       "version": "0.4.0",
@@ -193,12 +199,6 @@
       "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
       "dev": true
     },
-    "babylon": {
-      "version": "7.0.0-beta.19",
-      "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz",
-      "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==",
-      "dev": true
-    },
     "balanced-match": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@@ -231,9 +231,9 @@
       }
     },
     "bluebird": {
-      "version": "3.5.2",
-      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz",
-      "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==",
+      "version": "3.7.1",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz",
+      "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==",
       "dev": true
     },
     "brace-expansion": {
@@ -246,6 +246,11 @@
         "concat-map": "0.0.1"
       }
     },
+    "browser-or-node": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.2.1.tgz",
+      "integrity": "sha512-sVIA0cysIED0nbmNOm7sZzKfgN1rpFmrqvLZaFWspaBAftfQcezlC81G6j6U2RJf4Lh66zFxrCeOsvkUXIcPWg=="
+    },
     "buffer-alloc": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
@@ -296,12 +301,12 @@
       "dev": true
     },
     "catharsis": {
-      "version": "0.8.9",
-      "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz",
-      "integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=",
+      "version": "0.8.11",
+      "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz",
+      "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==",
       "dev": true,
       "requires": {
-        "underscore-contrib": "~0.3.0"
+        "lodash": "^4.17.14"
       }
     },
     "chalk": {
@@ -560,6 +565,12 @@
         "once": "^1.4.0"
       }
     },
+    "entities": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+      "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
+      "dev": true
+    },
     "es-abstract": {
       "version": "1.12.0",
       "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
@@ -715,10 +726,21 @@
       }
     },
     "eslint-utils": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz",
-      "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==",
-      "dev": true
+      "version": "1.4.3",
+      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
+      "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
+      "dev": true,
+      "requires": {
+        "eslint-visitor-keys": "^1.1.0"
+      },
+      "dependencies": {
+        "eslint-visitor-keys": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
+          "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
+          "dev": true
+        }
+      }
     },
     "eslint-visitor-keys": {
       "version": "1.0.0",
@@ -1315,6 +1337,11 @@
       "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
       "dev": true
     },
+    "isomorphic-ws": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz",
+      "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w=="
+    },
     "isstream": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
@@ -1386,9 +1413,9 @@
       "dev": true
     },
     "js-yaml": {
-      "version": "3.12.0",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
-      "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
+      "version": "3.13.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+      "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
       "dev": true,
       "requires": {
         "argparse": "^1.0.7",
@@ -1396,12 +1423,12 @@
       }
     },
     "js2xmlparser": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz",
-      "integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.0.tgz",
+      "integrity": "sha512-WuNgdZOXVmBk5kUPMcTcVUpbGRzLfNkv7+7APq7WiDihpXVKrgxo6wwRpRl9OQeEBgKCVk9mR7RbzrnNWC8oBw==",
       "dev": true,
       "requires": {
-        "xmlcreate": "^1.0.1"
+        "xmlcreate": "^2.0.0"
       }
     },
     "jsbn": {
@@ -1411,23 +1438,39 @@
       "dev": true
     },
     "jsdoc": {
-      "version": "3.5.5",
-      "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz",
-      "integrity": "sha512-6PxB65TAU4WO0Wzyr/4/YhlGovXl0EVYfpKbpSroSj0qBxT4/xod/l40Opkm38dRHRdQgdeY836M0uVnJQG7kg==",
+      "version": "3.6.3",
+      "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.3.tgz",
+      "integrity": "sha512-Yf1ZKA3r9nvtMWHO1kEuMZTlHOF8uoQ0vyo5eH7SQy5YeIiHM+B0DgKnn+X6y6KDYZcF7G2SPkKF+JORCXWE/A==",
       "dev": true,
       "requires": {
-        "babylon": "7.0.0-beta.19",
-        "bluebird": "~3.5.0",
-        "catharsis": "~0.8.9",
-        "escape-string-regexp": "~1.0.5",
-        "js2xmlparser": "~3.0.0",
-        "klaw": "~2.0.0",
-        "marked": "~0.3.6",
-        "mkdirp": "~0.5.1",
-        "requizzle": "~0.2.1",
-        "strip-json-comments": "~2.0.1",
+        "@babel/parser": "^7.4.4",
+        "bluebird": "^3.5.4",
+        "catharsis": "^0.8.11",
+        "escape-string-regexp": "^2.0.0",
+        "js2xmlparser": "^4.0.0",
+        "klaw": "^3.0.0",
+        "markdown-it": "^8.4.2",
+        "markdown-it-anchor": "^5.0.2",
+        "marked": "^0.7.0",
+        "mkdirp": "^0.5.1",
+        "requizzle": "^0.2.3",
+        "strip-json-comments": "^3.0.1",
         "taffydb": "2.6.2",
-        "underscore": "~1.8.3"
+        "underscore": "~1.9.1"
+      },
+      "dependencies": {
+        "escape-string-regexp": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+          "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+          "dev": true
+        },
+        "strip-json-comments": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz",
+          "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==",
+          "dev": true
+        }
       }
     },
     "json-int64": {
@@ -1476,9 +1519,9 @@
       }
     },
     "klaw": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz",
-      "integrity": "sha1-WcEo4Nxc5BAgEVEZTuucv4WGUPY=",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz",
+      "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==",
       "dev": true,
       "requires": {
         "graceful-fs": "^4.1.9"
@@ -1494,16 +1537,50 @@
         "type-check": "~0.3.2"
       }
     },
+    "linkify-it": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
+      "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
+      "dev": true,
+      "requires": {
+        "uc.micro": "^1.0.1"
+      }
+    },
     "lodash": {
-      "version": "4.17.11",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
-      "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
+      "version": "4.17.15",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+      "dev": true
+    },
+    "markdown-it": {
+      "version": "8.4.2",
+      "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz",
+      "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==",
+      "dev": true,
+      "requires": {
+        "argparse": "^1.0.7",
+        "entities": "~1.1.1",
+        "linkify-it": "^2.0.0",
+        "mdurl": "^1.0.1",
+        "uc.micro": "^1.0.5"
+      }
+    },
+    "markdown-it-anchor": {
+      "version": "5.2.5",
+      "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.2.5.tgz",
+      "integrity": "sha512-xLIjLQmtym3QpoY9llBgApknl7pxAcN3WDRc2d3rwpl+/YvDZHPmKscGs+L6E05xf2KrCXPBvosWt7MZukwSpQ==",
       "dev": true
     },
     "marked": {
-      "version": "0.3.19",
-      "resolved": "http://registry.npmjs.org/marked/-/marked-0.3.19.tgz",
-      "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==",
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz",
+      "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==",
+      "dev": true
+    },
+    "mdurl": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+      "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
       "dev": true
     },
     "mime-db": {
@@ -1969,20 +2046,12 @@
       }
     },
     "requizzle": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz",
-      "integrity": "sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=",
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz",
+      "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==",
       "dev": true,
       "requires": {
-        "underscore": "~1.6.0"
-      },
-      "dependencies": {
-        "underscore": {
-          "version": "1.6.0",
-          "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
-          "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=",
-          "dev": true
-        }
+        "lodash": "^4.17.14"
       }
     },
     "resolve": {
@@ -2383,6 +2452,12 @@
       "integrity": "sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==",
       "dev": true
     },
+    "uc.micro": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
+      "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
+      "dev": true
+    },
     "uglify-js": {
       "version": "3.4.9",
       "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz",
@@ -2411,28 +2486,11 @@
       }
     },
     "underscore": {
-      "version": "1.8.3",
-      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
-      "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=",
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
+      "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==",
       "dev": true
     },
-    "underscore-contrib": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz",
-      "integrity": "sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=",
-      "dev": true,
-      "requires": {
-        "underscore": "1.6.0"
-      },
-      "dependencies": {
-        "underscore": {
-          "version": "1.6.0",
-          "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
-          "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=",
-          "dev": true
-        }
-      }
-    },
     "unpipe": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
@@ -2548,9 +2606,9 @@
       }
     },
     "xmlcreate": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz",
-      "integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.1.tgz",
+      "integrity": "sha512-MjGsXhKG8YjTKrDCXseFo3ClbMGvUD4en29H2Cev1dv4P/chlpw6KdYmlCWDkhosBVKRDjM836+3e3pm1cBNJA==",
       "dev": true
     },
     "xtend": {
diff --git a/package.json b/package.json
index c674fef..c803df5 100644
--- a/package.json
+++ b/package.json
@@ -33,14 +33,19 @@
   "browser": "./lib/nodejs/lib/thrift/browser.js",
   "main": "./lib/nodejs/lib/thrift",
   "engines": {
-    "node": ">= 4.1.0"
+    "node": ">= 10.18.0"
   },
   "dependencies": {
+    "browser-or-node": "^1.2.1",
+    "isomorphic-ws": "^4.0.1",
     "node-int64": "^0.4.0",
     "q": "^1.5.0",
-    "ws": "^5.0.0"
+    "ws": "^5.2.2"
   },
   "devDependencies": {
+    "@types/node": "^10.12.6",
+    "@types/node-int64": "^0.4.29",
+    "@types/q": "^1.5.1",
     "buffer-equals": "^1.0.4",
     "commander": "^2.14.1",
     "connect": "^3.6.6",
@@ -49,15 +54,12 @@
     "eslint-plugin-prettier": "^3.0.0",
     "html-validator-cli": "^4.1.4",
     "istanbul": "^0.4.5",
-    "jsdoc": "^3.5.5",
+    "jsdoc": "^3.6.3",
     "json-int64": "^1.0.0",
     "prettier": "^1.14.3",
     "tape": "^4.9.0",
-    "utf-8-validate": "^4.0.0",
     "typescript": "^3.1.6",
-    "@types/node": "^10.12.6",
-    "@types/node-int64": "^0.4.29",
-    "@types/q": "^1.5.1"
+    "utf-8-validate": "^4.0.0"
   },
   "scripts": {
     "cover": "lib/nodejs/test/testAll.sh COVER",