You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by ra...@apache.org on 2014/05/11 09:27:08 UTC

git commit: THRIFT-2511 Node.js compact protocol Client: Node Patch: Randy Abernethy

Repository: thrift
Updated Branches:
  refs/heads/master facc8dc6c -> 20aeba3e3


THRIFT-2511 Node.js compact protocol
Client: Node
Patch: Randy Abernethy

Adds Compact Protocol to Node.js, tests in testAll.sh and repairs all
library JSHint warnings.


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/20aeba3e
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/20aeba3e
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/20aeba3e

Branch: refs/heads/master
Commit: 20aeba3e384f6590770dc3b4343e6d5dfcbd3ce1
Parents: facc8dc
Author: ra <ra...@apache.org>
Authored: Sun May 11 00:25:01 2014 -0700
Committer: ra <ra...@apache.org>
Committed: Sun May 11 00:25:01 2014 -0700

----------------------------------------------------------------------
 lib/nodejs/lib/thrift/binary.js               |   46 +-
 lib/nodejs/lib/thrift/index.js                |    1 +
 lib/nodejs/lib/thrift/protocol.js             | 1021 +++++++++++++++++---
 lib/nodejs/lib/thrift/thrift.js               |   76 +-
 lib/nodejs/lib/thrift/transport.js            |   14 +-
 lib/nodejs/test/client.js                     |    2 +
 lib/nodejs/test/server.js                     |    2 +
 lib/nodejs/test/testAll.sh                    |    7 +-
 lib/nodejs/test/thrift_test_driver.js         |   25 +-
 lib/nodejs/test/thrift_test_driver_promise.js |    2 +-
 10 files changed, 998 insertions(+), 198 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/20aeba3e/lib/nodejs/lib/thrift/binary.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/lib/thrift/binary.js b/lib/nodejs/lib/thrift/binary.js
index 62c3f72..9813ffd 100644
--- a/lib/nodejs/lib/thrift/binary.js
+++ b/lib/nodejs/lib/thrift/binary.js
@@ -17,18 +17,18 @@
  * under the License.
  */
 
-var POW_8 = Math.pow(2, 8)
-var POW_16 = Math.pow(2, 16)
-var POW_24 = Math.pow(2, 24)
-var POW_32 = Math.pow(2, 32)
-var POW_40 = Math.pow(2, 40)
-var POW_48 = Math.pow(2, 48)
-var POW_52 = Math.pow(2, 52)
-var POW_1022 = Math.pow(2, 1022)
-
-exports.readByte = function(byte){
-	return byte > 127 ? byte-256 : byte;
-}
+var POW_8 = Math.pow(2, 8);
+var POW_16 = Math.pow(2, 16);
+var POW_24 = Math.pow(2, 24);
+var POW_32 = Math.pow(2, 32);
+var POW_40 = Math.pow(2, 40);
+var POW_48 = Math.pow(2, 48);
+var POW_52 = Math.pow(2, 52);
+var POW_1022 = Math.pow(2, 1022);
+
+exports.readByte = function(b){
+	return b > 127 ? b-256 : b;
+};
 
 exports.readI16 = function(buff, off) {
   off = off || 0;
@@ -38,7 +38,7 @@ exports.readI16 = function(buff, off) {
     v -= POW_16;
   }
   return v;
-}
+};
 
 exports.readI32 = function(buff, off) {
   off = off || 0;
@@ -50,14 +50,14 @@ exports.readI32 = function(buff, off) {
     v -= POW_32;
   }
   return v;
-}
+};
 
 exports.writeI16 = function(buff, v) {
   buff[1] = v & 0xff;
   v >>= 8;
   buff[0] = v & 0xff;
   return buff;
-}
+};
 
 exports.writeI32 = function(buff, v) {
   buff[3] = v & 0xff;
@@ -68,7 +68,7 @@ exports.writeI32 = function(buff, v) {
   v >>= 8;
   buff[0] = v & 0xff;
   return buff;
-}
+};
 
 exports.readDouble = function(buff, off) {
   off = off || 0;
@@ -86,7 +86,7 @@ exports.readDouble = function(buff, off) {
 
   switch (e) {
     case 0:
-      e = -1022
+      e = -1022;
       break;
     case 2047:
       return m ? NaN : (signed ? -Infinity : Infinity);
@@ -100,7 +100,7 @@ exports.readDouble = function(buff, off) {
   }
 
   return m * Math.pow(2, e - 52);
-}
+};
 
 /*
  * Based on code from the jspack module:
@@ -109,9 +109,9 @@ exports.readDouble = function(buff, off) {
 exports.writeDouble = function(buff, v) {
   var m, e, c;
 
-  buff[0] = (v < 0 ? 0x80 : 0x00)
+  buff[0] = (v < 0 ? 0x80 : 0x00);
 
-  v = Math.abs(v)
+  v = Math.abs(v);
   if (v !== v) {
     // NaN, use QNaN IEEE format
     m = 2251799813685248;
@@ -120,8 +120,8 @@ exports.writeDouble = function(buff, v) {
     m = 0;
     e = 2047;
   } else {
-    e = Math.floor(Math.log(v) / Math.LN2)
-    c = Math.pow(2, -e)
+    e = Math.floor(Math.log(v) / Math.LN2);
+    c = Math.pow(2, -e);
     if (v * c < 1) {
       e--;
       c *= 2;
@@ -165,4 +165,4 @@ exports.writeDouble = function(buff, v) {
   buff[1] |= m & 0x0f;
 
   return buff;
-}
+};

http://git-wip-us.apache.org/repos/asf/thrift/blob/20aeba3e/lib/nodejs/lib/thrift/index.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/lib/thrift/index.js b/lib/nodejs/lib/thrift/index.js
index 3a865f8..ea7fde0 100644
--- a/lib/nodejs/lib/thrift/index.js
+++ b/lib/nodejs/lib/thrift/index.js
@@ -54,3 +54,4 @@ exports.TFramedTransport = require('./transport').TFramedTransport;
 exports.TBufferedTransport = require('./transport').TBufferedTransport;
 exports.TBinaryProtocol = require('./protocol').TBinaryProtocol;
 exports.TJSONProtocol = require('./protocol').TJSONProtocol;
+exports.TCompactProtocol = require('./protocol').TCompactProtocol;

http://git-wip-us.apache.org/repos/asf/thrift/blob/20aeba3e/lib/nodejs/lib/thrift/protocol.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/lib/thrift/protocol.js b/lib/nodejs/lib/thrift/protocol.js
index 3cf3f41..8ccb55d 100644
--- a/lib/nodejs/lib/thrift/protocol.js
+++ b/lib/nodejs/lib/thrift/protocol.js
@@ -37,13 +37,20 @@ var TProtocolException = function(type, message) {
   Error.call(this, message);
   this.name = 'TProtocolException';
   this.type = type;
-}
+};
 util.inherits(TProtocolException, Error);
 
-// NastyHaxx. JavaScript forces hex constants to be
-// positive, converting this into a long. If we hardcode the int value
-// instead it'll stay in 32 bit-land.
-var VERSION_MASK = -65536, // 0xffff0000
+
+//
+// BINARY PROTOCOL
+//
+///////////////////////////////////////////////////////////
+
+// JavaScript supports only numeric doubles, therefore even hex values are always signed.
+// The largest integer value which can be represented in JavaScript is +/-2^53.
+// Bitwise operations convert numbers to 32 bit integers but perform sign extension
+// upon assigning values back to variables.
+var VERSION_MASK = -65536,   // 0xffff0000
     VERSION_1 = -2147418112, // 0x80010000
     TYPE_MASK = 0x000000ff;
 
@@ -51,11 +58,11 @@ var TBinaryProtocol = exports.TBinaryProtocol = function(trans, strictRead, stri
   this.trans = trans;
   this.strictRead = (strictRead !== undefined ? strictRead : false);
   this.strictWrite = (strictWrite !== undefined ? strictWrite : true);
-}
+};
 
 TBinaryProtocol.prototype.flush = function() {
   return this.trans.flush();
-}
+};
 
 TBinaryProtocol.prototype.writeMessageBegin = function(name, type, seqid) {
     if (this.strictWrite) {
@@ -67,53 +74,53 @@ TBinaryProtocol.prototype.writeMessageBegin = function(name, type, seqid) {
       this.writeByte(type);
       this.writeI32(seqid);
     }
-}
+};
 
 TBinaryProtocol.prototype.writeMessageEnd = function() {
-}
+};
 
 TBinaryProtocol.prototype.writeStructBegin = function(name) {
-}
+};
 
 TBinaryProtocol.prototype.writeStructEnd = function() {
-}
+};
 
 TBinaryProtocol.prototype.writeFieldBegin = function(name, type, id) {
   this.writeByte(type);
   this.writeI16(id);
-}
+};
 
 TBinaryProtocol.prototype.writeFieldEnd = function() {
-}
+};
 
 TBinaryProtocol.prototype.writeFieldStop = function() {
   this.writeByte(Type.STOP);
-}
+};
 
 TBinaryProtocol.prototype.writeMapBegin = function(ktype, vtype, size) {
   this.writeByte(ktype);
   this.writeByte(vtype);
   this.writeI32(size);
-}
+};
 
 TBinaryProtocol.prototype.writeMapEnd = function() {
-}
+};
 
 TBinaryProtocol.prototype.writeListBegin = function(etype, size) {
   this.writeByte(etype);
   this.writeI32(size);
-}
+};
 
 TBinaryProtocol.prototype.writeListEnd = function() {
-}
+};
 
 TBinaryProtocol.prototype.writeSetBegin = function(etype, size) {
   this.writeByte(etype);
   this.writeI32(size);
-}
+};
 
 TBinaryProtocol.prototype.writeSetEnd = function() {
-}
+};
 
 TBinaryProtocol.prototype.writeBool = function(bool) {
   if (bool) {
@@ -121,55 +128,55 @@ TBinaryProtocol.prototype.writeBool = function(bool) {
   } else {
     this.writeByte(0);
   }
-}
+};
 
-TBinaryProtocol.prototype.writeByte = function(byte) {
-  this.trans.write(new Buffer([byte]));
-}
+TBinaryProtocol.prototype.writeByte = function(b) {
+  this.trans.write(new Buffer([b]));
+};
 
 TBinaryProtocol.prototype.writeI16 = function(i16) {
   this.trans.write(binary.writeI16(new Buffer(2), i16));
-}
+};
 
 TBinaryProtocol.prototype.writeI32 = function(i32) {
   this.trans.write(binary.writeI32(new Buffer(4), i32));
-}
+};
 
 TBinaryProtocol.prototype.writeI64 = function(i64) {
   if (i64.buffer) {
     this.trans.write(i64.buffer);
   } else {
-    this.trans.write(new Int64(i64).buffer)
+    this.trans.write(new Int64(i64).buffer);
   }
-}
+};
 
 TBinaryProtocol.prototype.writeDouble = function(dub) {
   this.trans.write(binary.writeDouble(new Buffer(8), dub));
-}
+};
 
 TBinaryProtocol.prototype.writeString = function(arg) {
   if (typeof(arg) === 'string') {
-    this.writeI32(Buffer.byteLength(arg, 'utf8'))
+    this.writeI32(Buffer.byteLength(arg, 'utf8'));
     this.trans.write(arg, 'utf8');
   } else if (arg instanceof Buffer) {
-    this.writeI32(arg.length)
+    this.writeI32(arg.length);
     this.trans.write(arg);
   } else {
-    throw new Error('writeString called without a string/Buffer argument: ' + arg)
+    throw new Error('writeString called without a string/Buffer argument: ' + arg);
   }
-}
+};
 
 TBinaryProtocol.prototype.writeBinary = function(arg) {
   if (typeof(arg) === 'string') {
-    this.writeI32(Buffer.byteLength(arg, 'utf8'))
+    this.writeI32(Buffer.byteLength(arg, 'utf8'));
     this.trans.write(arg, 'utf8');
   } else if (arg instanceof Buffer) {
-    this.writeI32(arg.length)
+    this.writeI32(arg.length);
     this.trans.write(arg);
   } else {
-    throw new Error('writeBinary called without a string/Buffer argument: ' + arg)
+    throw new Error('writeBinary called without a string/Buffer argument: ' + arg);
   }
-}
+};
 
 TBinaryProtocol.prototype.readMessageBegin = function() {
   var sz = this.readI32();
@@ -193,17 +200,17 @@ TBinaryProtocol.prototype.readMessageBegin = function() {
     seqid = this.readI32();
   }
   return {fname: name, mtype: type, rseqid: seqid};
-}
+};
 
 TBinaryProtocol.prototype.readMessageEnd = function() {
-}
+};
 
 TBinaryProtocol.prototype.readStructBegin = function() {
-  return {fname: ''}
-}
+  return {fname: ''};
+};
 
 TBinaryProtocol.prototype.readStructEnd = function() {
-}
+};
 
 TBinaryProtocol.prototype.readFieldBegin = function() {
   var type = this.readByte();
@@ -212,81 +219,81 @@ TBinaryProtocol.prototype.readFieldBegin = function() {
   }
   var id = this.readI16();
   return {fname: null, ftype: type, fid: id};
-}
+};
 
 TBinaryProtocol.prototype.readFieldEnd = function() {
-}
+};
 
 TBinaryProtocol.prototype.readMapBegin = function() {
   var ktype = this.readByte();
   var vtype = this.readByte();
   var size = this.readI32();
   return {ktype: ktype, vtype: vtype, size: size};
-}
+};
 
 TBinaryProtocol.prototype.readMapEnd = function() {
-}
+};
 
 TBinaryProtocol.prototype.readListBegin = function() {
   var etype = this.readByte();
   var size = this.readI32();
   return {etype: etype, size: size};
-}
+};
 
 TBinaryProtocol.prototype.readListEnd = function() {
-}
+};
 
 TBinaryProtocol.prototype.readSetBegin = function() {
   var etype = this.readByte();
   var size = this.readI32();
   return {etype: etype, size: size};
-}
+};
 
 TBinaryProtocol.prototype.readSetEnd = function() {
-}
+};
 
 TBinaryProtocol.prototype.readBool = function() {
-  var byte = this.readByte();
-  if (byte == 0) {
+  var b = this.readByte();
+  if (b === 0) {
     return false;
   }
   return true;
-}
+};
 
 TBinaryProtocol.prototype.readByte = function() {
   return this.trans.readByte();
-}
+};
 
 TBinaryProtocol.prototype.readI16 = function() {
   return this.trans.readI16();
-}
+};
 
 TBinaryProtocol.prototype.readI32 = function() {
   return this.trans.readI32();
-}
+};
 
 TBinaryProtocol.prototype.readI64 = function() {
   var buff = this.trans.read(8);
   return new Int64(buff);
-}
+};
 
 TBinaryProtocol.prototype.readDouble = function() {
   return this.trans.readDouble();
-}
+};
 
 TBinaryProtocol.prototype.readBinary = function() {
   var len = this.readI32();
   return this.trans.read(len);
-}
+};
 
 TBinaryProtocol.prototype.readString = function() {
   var len = this.readI32();
   return this.trans.readString(len);
-}
+};
 
 TBinaryProtocol.prototype.getTransport = function() {
   return this.trans;
-}
+};
 
 TBinaryProtocol.prototype.skip = function(type) {
   switch (type) {
@@ -326,35 +333,815 @@ TBinaryProtocol.prototype.skip = function(type) {
       this.readStructEnd();
       break;
     case Type.MAP:
-      var r = this.readMapBegin();
-      for (var i = 0; i < r.size; ++i) {
-        this.skip(r.ktype);
-        this.skip(r.vtype);
+      var mapBegin = this.readMapBegin();
+      for (var i = 0; i < mapBegin.size; ++i) {
+        this.skip(mapBegin.ktype);
+        this.skip(mapBegin.vtype);
       }
       this.readMapEnd();
       break;
     case Type.SET:
-      var r = this.readSetBegin();
-      for (var i = 0; i < r.size; ++i) {
-        this.skip(r.etype);
+      var setBegin = this.readSetBegin();
+      for (var i2 = 0; i2 < setBegin.size; ++i2) {
+        this.skip(setBegin.etype);
       }
       this.readSetEnd();
       break;
     case Type.LIST:
-      var r = this.readListBegin();
-      for (var i = 0; i < r.size; ++i) {
-        this.skip(r.etype);
+      var listBegin = this.readListBegin();
+      for (var i3 = 0; i3 < listBegin.size; ++i3) {
+        this.skip(listBegin.etype);
       }
       this.readListEnd();
       break;
     default:
       throw new  Error("Invalid type: " + type);
   }
-}
+};
+
+
+//
+// COMPACT PROTOCOL
+//
+///////////////////////////////////////////////////////////
+
+/**
+ * Constructor Function for the Compact Protocol.
+ * @constructor
+ * @param {object} [trans] - The underlying transport to read/write.
+ * @classdesc The Apache Thrift Protocol layer performs serialization
+ *     of base types, the compact protocol serializes data in binary 
+ *     form with minimal space used for scalar values.
+ */
+var TCompactProtocol = exports.TCompactProtocol = function(trans) {
+  this.trans = trans;
+  this.lastField_ = [];
+  this.lastFieldId_ = 0;
+  this.string_limit_ = 0;
+  this.string_buf_ = null;
+  this.string_buf_size_ = 0;
+  this.container_limit_ = 0;
+  this.booleanField_ = {
+    name: null,
+    hasBoolValue: false
+  };
+  this.boolValue_ = {
+    hasBoolValue: false,
+    boolValue: false
+  };
+};
+
+
+//
+// Compact Protocol Constants
+//
+
+/**
+  * Compact Protocol ID number.
+  * @readonly
+  * @const {number} PROTOCOL_ID
+  */
+TCompactProtocol.PROTOCOL_ID = -126;  //1000 0010
+
+/**
+  * Compact Protocol version number.
+  * @readonly
+  * @const {number} VERSION_N
+  */
+TCompactProtocol.VERSION_N = 1;
+
+/**
+  * Compact Protocol version mask for combining protocol version and message type in one byte.
+  * @readonly
+  * @const {number} VERSION_MASK
+  */
+TCompactProtocol.VERSION_MASK = 0x1f; //0001 1111
+
+/**
+  * Compact Protocol message type mask for combining protocol version and message type in one byte.
+  * @readonly
+  * @const {number} TYPE_MASK
+  */
+TCompactProtocol.TYPE_MASK = -32;     //1110 0000
+
+/**
+  * Compact Protocol message type shift amount for combining protocol version and message type in one byte.
+  * @readonly
+  * @const {number} TYPE_SHIFT_AMOUNT
+  */
+TCompactProtocol.TYPE_SHIFT_AMOUNT = 5;
+
+/**
+ * Compact Protocol type IDs used to keep type data within one nibble.
+ * @readonly
+ * @property {number}  CT_STOP          - End of a set of fields.
+ * @property {number}  CT_BOOLEAN_TRUE  - Flag for Boolean field with true value (packed field and value).
+ * @property {number}  CT_BOOLEAN_FALSE - Flag for Boolean field with false value (packed field and value).
+ * @property {number}  CT_BYTE          - Signed 8 bit integer.
+ * @property {number}  CT_I16           - Signed 16 bit integer.
+ * @property {number}  CT_I32           - Signed 32 bit integer.
+ * @property {number}  CT_I64           - Signed 64 bit integer (2^53 max in JavaScript).
+ * @property {number}  CT_DOUBLE        - 64 bit IEEE 854 floating point.
+ * @property {number}  CT_BINARY        - Array of bytes (used for strings also).
+ * @property {number}  CT_LIST          - A collection type (unordered).
+ * @property {number}  CT_SET           - A collection type (unordered and without repeated values).
+ * @property {number}  CT_MAP           - A collection type (map/associative-array/dictionary).
+ * @property {number}  CT_STRUCT        - A multifield type.
+ */
+TCompactProtocol.Types = {
+  CT_STOP:           0x00,
+  CT_BOOLEAN_TRUE:   0x01,
+  CT_BOOLEAN_FALSE:  0x02,
+  CT_BYTE:           0x03,
+  CT_I16:            0x04,
+  CT_I32:            0x05,
+  CT_I64:            0x06,
+  CT_DOUBLE:         0x07,
+  CT_BINARY:         0x08,
+  CT_LIST:           0x09,
+  CT_SET:            0x0A,
+  CT_MAP:            0x0B,
+  CT_STRUCT:         0x0C
+};
+
+/**
+ * Array mapping Compact type IDs to standard Thrift type IDs.
+ * @readonly
+ */
+TCompactProtocol.TTypeToCType = [
+  TCompactProtocol.Types.CT_STOP,         // T_STOP
+  0,                                      // unused
+  TCompactProtocol.Types.CT_BOOLEAN_TRUE, // T_BOOL
+  TCompactProtocol.Types.CT_BYTE,         // T_BYTE
+  TCompactProtocol.Types.CT_DOUBLE,       // T_DOUBLE
+  0,                                      // unused
+  TCompactProtocol.Types.CT_I16,          // T_I16
+  0,                                      // unused
+  TCompactProtocol.Types.CT_I32,          // T_I32
+  0,                                      // unused
+  TCompactProtocol.Types.CT_I64,          // T_I64
+  TCompactProtocol.Types.CT_BINARY,       // T_STRING
+  TCompactProtocol.Types.CT_STRUCT,       // T_STRUCT
+  TCompactProtocol.Types.CT_MAP,          // T_MAP
+  TCompactProtocol.Types.CT_SET,          // T_SET
+  TCompactProtocol.Types.CT_LIST,         // T_LIST
+];
+
+
+//
+// Compact Protocol Utilities
+//
+
+/**
+ * Returns the underlying transport layer.
+ * @return {object} The underlying transport layer.
+ */TCompactProtocol.prototype.getTransport = function() {
+  return this.trans;
+};
+
+/**
+ * Lookup a Compact Protocol Type value for a given Thrift Type value.
+ * N.B. Used only internally.
+ * @param {number} ttype - Thrift type value
+ * @returns {number} Compact protocol type value
+ */
+TCompactProtocol.prototype.getCompactType = function(ttype) {
+  return TCompactProtocol.TTypeToCType[ttype];
+};
+
+/**
+ * Lookup a Thrift Type value for a given Compact Protocol Type value.
+ * N.B. Used only internally.
+ * @param {number} type - Compact Protocol type value
+ * @returns {number} Thrift Type value
+ */
+TCompactProtocol.prototype.getTType = function(type) {
+  switch (type) {
+    case Type.STOP:
+      return Type.STOP;
+    case TCompactProtocol.Types.CT_BOOLEAN_FALSE:
+    case TCompactProtocol.Types.CT_BOOLEAN_TRUE:
+      return Type.BOOL;
+    case TCompactProtocol.Types.CT_BYTE:
+      return Type.BYTE;
+    case TCompactProtocol.Types.CT_I16:
+      return Type.I16;
+    case TCompactProtocol.Types.CT_I32:
+      return Type.I32;
+    case TCompactProtocol.Types.CT_I64:
+      return Type.I64;
+    case TCompactProtocol.Types.CT_DOUBLE:
+      return Type.DOUBLE;
+    case TCompactProtocol.Types.CT_BINARY:
+      return Type.STRING;
+    case TCompactProtocol.Types.CT_LIST:
+      return Type.LIST;
+    case TCompactProtocol.Types.CT_SET:
+      return Type.SET;
+    case TCompactProtocol.Types.CT_MAP:
+      return Type.MAP;
+    case TCompactProtocol.Types.CT_STRUCT:
+      return Type.STRUCT;
+    default:
+      throw new TProtocolException(INVALID_DATA, "Unknown type: " + type);
+  }
+  return Type.STOP;
+};
+
+
+//
+// Compact Protocol write operations
+//
+
+/**
+ * Send any buffered bytes to the end point.
+ */
+TCompactProtocol.prototype.flush = function() {
+  return this.trans.flush();
+};
+
+/**
+ * Writes an RPC message header
+ * @param {string} name - The method name for the message.
+ * @param {number} type - The type of message (CALL, REPLY, EXCEPTION, ONEWAY).
+ * @param {number} seqid - The call sequence number (if any).
+ */
+TCompactProtocol.prototype.writeMessageBegin = function(name, type, seqid) {
+  this.writeByte(TCompactProtocol.PROTOCOL_ID);
+  this.writeByte((TCompactProtocol.VERSION_N & TCompactProtocol.VERSION_MASK) | 
+                     ((type << TCompactProtocol.TYPE_SHIFT_AMOUNT) & TCompactProtocol.TYPE_MASK));
+  this.writeVarint32(seqid);
+  this.writeString(name);
+};
+
+TCompactProtocol.prototype.writeMessageEnd = function() {
+};
+
+TCompactProtocol.prototype.writeStructBegin = function(name) {
+  this.lastField_.push(this.lastFieldId_);
+  this.lastFieldId_ = 0;
+};
+
+TCompactProtocol.prototype.writeStructEnd = function() {
+  this.lastFieldId_ = this.lastField_.pop();
+};
+
+/**
+ * Writes a struct field header
+ * @param {string} name - The field name (not written with the compact protocol).
+ * @param {number} type - The field data type (a normal Thrift field Type).
+ * @param {number} id - The IDL field Id.
+ */
+TCompactProtocol.prototype.writeFieldBegin = function(name, type, id) {
+  if (type != Type.BOOL) {
+    return this.writeFieldBeginInternal(name, type, id, -1);
+  }
+
+  this.booleanField_.name = name;
+  this.booleanField_.fieldType = type;
+  this.booleanField_.fieldId = id;
+};
+
+TCompactProtocol.prototype.writeFieldEnd = function() {
+};
+
+TCompactProtocol.prototype.writeFieldStop = function() {
+  this.writeByte(TCompactProtocol.Types.CT_STOP);
+};
+
+/**
+ * Writes a map collection header
+ * @param {number} keyType - The Thrift type of the map keys.
+ * @param {number} valType - The Thrift type of the map values.
+ * @param {number} size - The number of k/v pairs in the map.
+ */
+TCompactProtocol.prototype.writeMapBegin = function(keyType, valType, size) {
+  if (size === 0) {
+    this.writeByte(0);
+  } else {
+    this.writeVarint32(size);
+    this.writeByte(this.getCompactType(keyType) << 4 | this.getCompactType(valType));
+  }
+};
+
+TCompactProtocol.prototype.writeMapEnd = function() {
+};
+
+/**
+ * Writes a list collection header
+ * @param {number} elemType - The Thrift type of the list elements.
+ * @param {number} size - The number of elements in the list.
+ */
+TCompactProtocol.prototype.writeListBegin = function(elemType, size) {
+  this.writeCollectionBegin(elemType, size);
+};
+
+TCompactProtocol.prototype.writeListEnd = function() {
+};
+
+/**
+ * Writes a set collection header
+ * @param {number} elemType - The Thrift type of the set elements.
+ * @param {number} size - The number of elements in the set.
+ */
+TCompactProtocol.prototype.writeSetBegin = function(elemType, size) {
+  this.writeCollectionBegin(elemType, size);
+};
+
+TCompactProtocol.prototype.writeSetEnd = function() {
+};
+
+TCompactProtocol.prototype.writeBool = function(value) {
+  if (booleanField_.name != NULL) {
+    // we haven't written the field header yet
+    this.writeFieldBeginInternal(booleanField_.name,
+                                 booleanField_.fieldType,
+                                 booleanField_.fieldId,
+                                 (value ? TCompactProtocol.Types.CT_BOOLEAN_TRUE
+                                          : TCompactProtocol.Types.CT_BOOLEAN_FALSE));
+    booleanField_.name = NULL;
+  } else {
+    // we're not part of a field, so just write the value
+    this.writeByte((value ? TCompactProtocol.Types.CT_BOOLEAN_TRUE
+                            : TCompactProtocol.Types.CT_BOOLEAN_FALSE));
+  }
+};
+
+TCompactProtocol.prototype.writeByte = function(b) {
+  this.trans.write(new Buffer([b]));
+};
+
+TCompactProtocol.prototype.writeI16 = function(i16) {
+  this.writeVarint32(this.i32ToZigzag(i16));  
+};
+
+TCompactProtocol.prototype.writeI32 = function(i32) {
+  this.writeVarint32(this.i32ToZigzag(i32));  
+};
+
+TCompactProtocol.prototype.writeI64 = function(i64) {
+  this.writeVarint64(this.i64ToZigzag(i64));
+};
+
+TCompactProtocol.prototype.writeDouble = function(dub) {
+  this.trans.write(binary.writeDouble(new Buffer(8), dub));
+};
+
+TCompactProtocol.prototype.writeString = function(arg) {
+  this.writeBinary(arg);
+};
+
+TCompactProtocol.prototype.writeBinary = function(arg) {
+  if (typeof arg === 'string') {
+    this.writeVarint32(Buffer.byteLength(arg, 'utf8')) ;
+    this.trans.write(arg, 'utf8');
+  } else if (arg instanceof Buffer) {
+    this.writeVarint32(arg.length);
+    this.trans.write(arg);
+  } else {
+    throw new Error('writeString/writeBinary called without a string/Buffer argument: ' + arg);
+  }
+};
+
+
+//
+// Compact Protocol internal write methods
+//
+
+TCompactProtocol.prototype.writeFieldBeginInternal = function(name,
+                                                              fieldType,
+                                                              fieldId,
+                                                              typeOverride) {
+  //If there's a type override, use that.
+  var typeToWrite = (typeOverride == -1 ? this.getCompactType(fieldType) : typeOverride);
+  //Check if we can delta encode the field id
+  if (fieldId > this.lastFieldId_ && fieldId - this.lastFieldId_ <= 15) {
+    //Include the type delta with the field ID
+    this.writeByte((fieldId - this.lastFieldId_) << 4 | typeToWrite);
+  } else {
+    //Write separate type and ID values
+    this.writeByte(typeToWrite);
+    this.writeI16(fieldId);
+  }
+  this.lastFieldId_ = fieldId;
+};
+
+TCompactProtocol.prototype.writeCollectionBegin = function(elemType, size) {
+  if (size <= 14) {
+    //Combine size and type in one byte if possible
+    this.writeByte(size << 4 | this.getCompactType(elemType));
+  } else {
+    this.writeByte(0xf0 | this.getCompactType(elemType));
+    this.writeVarint32(size);
+  }
+};
+
+/**
+ * Write an i32 as a varint. Results in 1-5 bytes on the wire.
+ */
+TCompactProtocol.prototype.writeVarint32 = function(n) {
+  var buf = new Buffer(5);
+  var wsize = 0;
+  while (true) {
+    if ((n & ~0x7F) === 0) {
+      buf[wsize++] = n;
+      break;
+    } else {
+      buf[wsize++] = ((n & 0x7F) | 0x80);
+      n = n >>> 7;
+    }
+  }
+  var wbuf = new Buffer(wsize);
+  buf.copy(wbuf,0,0,wsize);
+  this.trans.write(wbuf);
+};
+
+/**
+ * Write an i64 as a varint. Results in 1-10 bytes on the wire.
+ * N.B. node-int64 is always big endian
+ */
+TCompactProtocol.prototype.writeVarint64 = function(n) {
+  if (typeof n === "number"){
+    n = new Int64(n);
+  }
+  if (! (n instanceof Int64)) {
+    throw new TProtocolError(INVALID_DATA, "Expected Int64 or Number, found: " + n);
+  }
+  
+  var buf = new Buffer(10);
+  var wsize = 0;
+  var hi = n.buffer.readUInt32BE(0, true);
+  var lo = n.buffer.readUInt32BE(4, true);
+  var mask = 0;                                       
+  while (true) {
+    if (((lo & ~0x7F) === 0) && (hi === 0)) {
+      buf[wsize++] = lo;
+      break;
+    } else {
+      buf[wsize++] = ((lo & 0x7F) | 0x80);
+      mask = hi << 25;
+      lo = lo >>> 7;
+      hi = hi >>> 7;
+      lo = lo | mask;
+    }
+  }
+  var wbuf = new Buffer(wsize);
+  buf.copy(wbuf,0,0,wsize);
+  this.trans.write(wbuf);
+};
+
+/**
+ * Convert l into a zigzag long. This allows negative numbers to be
+ * represented compactly as a varint.
+ */
+TCompactProtocol.prototype.i64ToZigzag = function(l) {
+  if (typeof l === 'string') {
+    l = new Int64(parseInt(l, 10));
+  } else if (typeof l === 'number') {
+    l = new Int64(l);
+  }
+  if (! (l instanceof Int64)) {
+    throw new TProtocolException(INVALID_DATA, "Expected Int64 or Number, found: " + l);
+  }
+  var hi = l.buffer.readUInt32BE(0, true);
+  var lo = l.buffer.readUInt32BE(4, true);
+  var sign = hi >>> 31;
+  hi = ((hi << 1) | (lo >>> 31)) ^ ((!!sign) ? 0xFFFFFFFF : 0);
+  lo = (lo << 1) ^ ((!!sign) ? 0xFFFFFFFF : 0);
+  return new Int64(hi, lo);
+};
+
+/**
+ * Convert n into a zigzag int. This allows negative numbers to be
+ * represented compactly as a varint.
+ */
+TCompactProtocol.prototype.i32ToZigzag = function(n) {
+  return (n << 1) ^ ((n & 0x80000000) ? 0xFFFFFFFF : 0);
+};
+
+
+//
+// Compact Protocol read operations
+//
+
+TCompactProtocol.prototype.readMessageBegin = function() {
+  //Read protocol ID
+  var protocolId = this.trans.readByte();
+  if (protocolId != TCompactProtocol.PROTOCOL_ID) {
+    throw new TProtocolException(BAD_VERSION, "Bad protocol identifier " + protocolId);
+  }
+
+  //Read Version and Type
+  var versionAndType = this.trans.readByte();
+  var version = (versionAndType & TCompactProtocol.VERSION_MASK);
+  if (version != TCompactProtocol.VERSION_N) {
+    throw new TProtocolException(BAD_VERSION, "Bad protocol version " + version);
+  }
+  var type = ((versionAndType >> TCompactProtocol.TYPE_SHIFT_AMOUNT) & 0x03);
+
+  //Read SeqId
+  var seqid = this.readVarint32();
+  
+  //Read name
+  var name = this.readString();
+
+  return {fname: name, mtype: type, rseqid: seqid};
+};
+
+TCompactProtocol.prototype.readMessageEnd = function() {
+};
+
+TCompactProtocol.prototype.readStructBegin = function() {
+  this.lastField_.push(this.lastFieldId_);
+  this.lastFieldId_ = 0;
+  return {fname: ''};
+};
+
+TCompactProtocol.prototype.readStructEnd = function() {
+  this.lastFieldId_ = this.lastField_.pop();
+};
+
+TCompactProtocol.prototype.readFieldBegin = function() {
+  var fieldId = 0;
+  var b = this.trans.readByte(b);
+  var type = (b & 0x0f);
+
+  if (type == TCompactProtocol.Types.CT_STOP) {
+    return {fname: null, ftype: Thrift.Type.STOP, fid: 0};
+  }
+
+  //Mask off the 4 MSB of the type header to check for field id delta.
+  var modifier = ((b & 0x000000f0) >>> 4);
+  if (modifier === 0) {
+    //If not a delta read the field id.
+    fieldId = this.readI16();
+  } else {
+    //Recover the field id from the delta
+    fieldId = (this.lastFieldId_ + modifier);
+  }
+  var fieldType = this.getTType(type);
+
+  //Boolean are encoded with the type
+  if (type == TCompactProtocol.Types.CT_BOOLEAN_TRUE ||
+      type == TCompactProtocol.Types.CT_BOOLEAN_FALSE) {
+    this.boolValue_.hasBoolValue = true;
+    this.boolValue_.boolValue =
+      (type == TCompactProtocol.Types.CT_BOOLEAN_TRUE ? true : false);
+  }
+
+  //Save the new field for the next delta computation.
+  this.lastFieldId_ = fieldId;
+  return {fname: null, ftype: fieldType, fid: fieldId};
+};
+
+TCompactProtocol.prototype.readFieldEnd = function() {
+};
+
+TCompactProtocol.prototype.readMapBegin = function() {
+  var msize = this.readVarint32();
+  if (msize < 0) {
+    throw new TProtocolException(NEGATIVE_SIZE, "Negative map size");
+  } 
+
+  var kvtype = 0;
+  if (msize !== 0) {
+    kvType = this.trans.readByte();
+  }
+
+  var keyType = this.getTType((kvType & 0xf0) >>> 4);
+  var valType = this.getTType(kvType & 0xf);
+  return {ktype: keyType, vtype: valType, size: msize};
+};
+
+TCompactProtocol.prototype.readMapEnd = function() {
+};
+
+TCompactProtocol.prototype.readListBegin = function() {
+  var size_and_type = this.trans.readByte();
+
+  var lsize = (size_and_type >>> 4) & 0x0000000f;
+  if (lsize == 15) {
+    lsize = this.readVarint32();
+  }
+
+  if (lsize < 0) {
+    throw TProtocolException(NEGATIVE_SIZE, "Negative list size");
+  } 
+
+  var elemType = this.getTType(size_and_type & 0x0000000f);
+
+  return {etype: elemType, size: lsize};
+};
+
+TCompactProtocol.prototype.readListEnd = function() {
+};
+
+TCompactProtocol.prototype.readSetBegin = function() {
+  return this.readListBegin();
+};
+
+TCompactProtocol.prototype.readSetEnd = function() {
+};
+
+TCompactProtocol.prototype.readBool = function() {
+  var value = false;
+  var rsize = 0;
+  if (this.boolValue_.hasBoolValue === true) {
+    value = this.boolValue_.boolValue;
+    this.boolValue_.hasBoolValue = false;
+  } else {
+    var res = this.trans.readByte();
+    rsize = res.rsize;
+    value = (res.value == TCompactProtocol.Types.CT_BOOLEAN_TRUE);
+  }
+  return value;
+};
+
+TCompactProtocol.prototype.readByte = function() {
+  return this.trans.readByte();
+};
+
+TCompactProtocol.prototype.readI16 = function() {
+  return this.readI32();
+};
+
+TCompactProtocol.prototype.readI32 = function() {
+  return this.zigzagToI32(this.readVarint32());
+};
+
+TCompactProtocol.prototype.readI64 = function() {
+  return this.zigzagToI64(this.readVarint64());
+};
+
+TCompactProtocol.prototype.readDouble = function() {
+  return this.trans.readDouble();
+};
+
+TCompactProtocol.prototype.readBinary = function() {
+  var size = this.readVarint32();
+  // Catch empty string case
+  if (size === 0) {
+    return "";
+  }
+
+  // Catch error cases
+  if (size < 0) {
+    throw new TProtocolException(NEGATIVE_SIZE, "Negative binary/string size");
+  }
+  var value = this.trans.readString(size);
+
+  return value;  
+};
+
+TCompactProtocol.prototype.readString = function() {
+  return this.readBinary();
+};
+
+
+//
+// Compact Protocol internal read operations
+//
+
+/**
+ * Read an i32 from the wire as a varint. The MSB of each byte is set
+ * if there is another byte to follow. This can read up to 5 bytes.
+ */
+TCompactProtocol.prototype.readVarint32 = function() {
+  return this.readVarint64();
+};
+
+/**
+ * Read an i64 from the wire as a proper varint. The MSB of each byte is set
+ * if there is another byte to follow. This can read up to 10 bytes.
+ */
+TCompactProtocol.prototype.readVarint64 = function() {
+  var rsize = 0;
+  var lo = 0;
+  var hi = 0;
+  var shift = 0;
+  while (true) {
+    var b = this.trans.readByte();
+    rsize ++;
+    if (shift <= 25) {
+      lo = lo | ((b & 0x7f) << shift);
+    } else if (25 < shift && shift < 32) {
+      lo = lo | ((b & 0x7f) << shift);      
+      hi = hi | ((b & 0x7f) >>> (32-shift));      
+    } else {
+      hi = hi | ((b & 0x7f) << (shift-32));
+    }
+    shift += 7;
+    if (!(b & 0x80)) {
+      break;
+    }
+    if (rsize >= 10) {
+      throw new TProtocolException(INVALID_DATA, "Variable-length int over 10 bytes.");
+    }
+  }
+  var i64 = new Int64(hi, lo);
+  return i64.toNumber();
+};
+
+/**
+ * Convert from zigzag int to int.
+ */
+TCompactProtocol.prototype.zigzagToI32 = function(n) {
+  return (n >>> 1) ^ (-1 * (n & 1));
+};
+
+/**
+ * Convert from zigzag long to long.
+ */
+TCompactProtocol.prototype.zigzagToI64 = function(n) {
+  var zz = new Int64(n);
+  var hi = zz.buffer.readUInt32BE(0, true);
+  var lo = zz.buffer.readUInt32BE(4, true);
+  
+  var neg = new Int64(hi & 0, lo & 1);
+  neg._2scomp();
+  var hi_neg = neg.buffer.readUInt32BE(0, true);
+  var lo_neg = neg.buffer.readUInt32BE(4, true);
+  
+  var hi_lo = (hi << 31);
+  hi = (hi >>> 1) ^ (hi_neg);
+  lo = ((lo >>> 1) | hi_lo) ^ (lo_neg); 
+  var i64 = new Int64(hi, lo);
+  return i64.toNumber();
+};
+
+TCompactProtocol.prototype.skip = function(type) {
+  switch (type) {
+    case Type.STOP:
+      return;
+    case Type.BOOL:
+      this.readBool();
+      break;
+    case Type.BYTE:
+      this.readByte();
+      break;
+    case Type.I16:
+      this.readI16();
+      break;
+    case Type.I32:
+      this.readI32();
+      break;
+    case Type.I64:
+      this.readI64();
+      break;
+    case Type.DOUBLE:
+      this.readDouble();
+      break;
+    case Type.STRING:
+      this.readString();
+      break;
+    case Type.STRUCT:
+      this.readStructBegin();
+      while (true) {
+        var r = this.readFieldBegin();
+        if (r.ftype === Type.STOP) {
+          break;
+        }
+        this.skip(r.ftype);
+        this.readFieldEnd();
+      }
+      this.readStructEnd();
+      break;
+    case Type.MAP:
+      var mapBegin = this.readMapBegin();
+      for (var i = 0; i < mapBegin.size; ++i) {
+        this.skip(mapBegin.ktype);
+        this.skip(mapBegin.vtype);
+      }
+      this.readMapEnd();
+      break;
+    case Type.SET:
+      var setBegin = this.readSetBegin();
+      for (var i2 = 0; i2 < setBegin.size; ++i2) {
+        this.skip(setBegin.etype);
+      }
+      this.readSetEnd();
+      break;
+    case Type.LIST:
+      var listBegin = this.readListBegin();
+      for (var i3 = 0; i3 < listBegin.size; ++i3) {
+        this.skip(listBegin.etype);
+      }
+      this.readListEnd();
+      break;
+    default:
+      throw new  Error("Invalid type: " + type);
+  }
+};
+
+
+//
+// JSON PROTOCOL
+//
+///////////////////////////////////////////////////////////
 
 var TJSONProtocol = exports.TJSONProtocol = function(trans) {
   this.trans = trans;
-}
+};
 
 TJSONProtocol.Type = {};
 TJSONProtocol.Type[Thrift.Type.BOOL] = '"tf"';
@@ -387,14 +1174,14 @@ TJSONProtocol.Version = 1;
 
 TJSONProtocol.prototype.flush = function() {
   return this.trans.flush();
-}
+};
 
 TJSONProtocol.prototype.writeMessageBegin = function(name, messageType, seqid) {
   this.tstack = [];
   this.tpos = [];
 
   this.tstack.push([TJSONProtocol.Version, '"' + name + '"', messageType, seqid]);
-}
+};
 
 TJSONProtocol.prototype.writeMessageEnd = function() {
   var obj = this.tstack.pop();
@@ -405,12 +1192,12 @@ TJSONProtocol.prototype.writeMessageEnd = function() {
   this.wbuf = '[' + this.wobj.join(',') + ']';
 
   this.trans.write(this.wbuf);
-}
+};
 
 TJSONProtocol.prototype.writeStructBegin = function(name) {
   this.tpos.push(this.tstack.length);
   this.tstack.push({});
-}
+};
 
 TJSONProtocol.prototype.writeStructEnd = function() {
   var p = this.tpos.pop();
@@ -429,14 +1216,14 @@ TJSONProtocol.prototype.writeStructEnd = function() {
 
   str += '}';
   this.tstack[p] = str;
-}
+};
 
 TJSONProtocol.prototype.writeFieldBegin = function(name, fieldType, fieldId) {
   this.tpos.push(this.tstack.length);
   this.tstack.push({ 'fieldId': '"' +
     fieldId + '"', 'fieldType': TJSONProtocol.Type[fieldType]
   });
-}
+};
 
 TJSONProtocol.prototype.writeFieldEnd = function() {
   var value = this.tstack.pop();
@@ -450,16 +1237,16 @@ TJSONProtocol.prototype.writeFieldEnd = function() {
       fieldInfo.fieldType + ':' + value + '}';    
   }
   this.tpos.pop();
-}
+};
 
 TJSONProtocol.prototype.writeFieldStop = function() {
-}
+};
 
 TJSONProtocol.prototype.writeMapBegin = function(ktype, vtype, size) {
   //size is invalid, we'll set it on end.
   this.tpos.push(this.tstack.length);
   this.tstack.push([TJSONProtocol.Type[ktype], TJSONProtocol.Type[vtype], 0]);
-}
+};
 
 TJSONProtocol.prototype.writeMapEnd = function() {
   var p = this.tpos.pop();
@@ -494,12 +1281,12 @@ TJSONProtocol.prototype.writeMapEnd = function() {
 
   this.tstack[p].push(map);
   this.tstack[p] = '[' + this.tstack[p].join(',') + ']';
-}
+};
 
 TJSONProtocol.prototype.writeListBegin = function(etype, size) {
   this.tpos.push(this.tstack.length);
   this.tstack.push([TJSONProtocol.Type[etype], size]);
-}
+};
 
 TJSONProtocol.prototype.writeListEnd = function() {
   var p = this.tpos.pop();
@@ -511,12 +1298,12 @@ TJSONProtocol.prototype.writeListEnd = function() {
   }
 
   this.tstack[p] = '[' + this.tstack[p].join(',') + ']';
-}
+};
 
 TJSONProtocol.prototype.writeSetBegin = function(etype, size) {
     this.tpos.push(this.tstack.length);
     this.tstack.push([TJSONProtocol.Type[etype], size]);
-}
+};
 
 TJSONProtocol.prototype.writeSetEnd = function() {
   var p = this.tpos.pop();
@@ -528,31 +1315,31 @@ TJSONProtocol.prototype.writeSetEnd = function() {
   }
 
   this.tstack[p] = '[' + this.tstack[p].join(',') + ']';
-}
+};
 
 TJSONProtocol.prototype.writeBool = function(bool) {
   this.tstack.push(bool ? 1 : 0);
-}
+};
 
 TJSONProtocol.prototype.writeByte = function(byte) {
   this.tstack.push(byte);
-}
+};
 
 TJSONProtocol.prototype.writeI16 = function(i16) {
   this.tstack.push(i16);
-}
+};
 
 TJSONProtocol.prototype.writeI32 = function(i32) {
   this.tstack.push(i32);
-}
+};
 
 TJSONProtocol.prototype.writeI64 = function(i64) {
   this.tstack.push(i64);
-}
+};
 
 TJSONProtocol.prototype.writeDouble = function(dub) {
   this.tstack.push(dub);
-}
+};
 
 TJSONProtocol.prototype.writeString = function(str) {
   // We do not encode uri components for wire transfer:
@@ -591,11 +1378,11 @@ TJSONProtocol.prototype.writeString = function(str) {
       }
       this.tstack.push('"' + escapedString + '"');
   }
-}
+};
 
 TJSONProtocol.prototype.writeBinary = function(arg) {
   this.writeString(arg);
-}
+};
 
 TJSONProtocol.prototype.readMessageBegin = function() {
   this.rstack = [];
@@ -664,10 +1451,10 @@ TJSONProtocol.prototype.readMessageBegin = function() {
   r.rseqid = this.robj.shift();
   this.rstack.push(this.robj.shift());
   return r;
-}
+};
 
 TJSONProtocol.prototype.readMessageEnd = function() {
-}
+};
 
 TJSONProtocol.prototype.readStructBegin = function() {
   var r = {};
@@ -679,11 +1466,11 @@ TJSONProtocol.prototype.readStructBegin = function() {
   }
 
   return r;
-}
+};
 
 TJSONProtocol.prototype.readStructEnd = function() {
   this.rstack.pop();
-}
+};
 
 TJSONProtocol.prototype.readFieldBegin = function() {
   var r = {};
@@ -728,7 +1515,7 @@ TJSONProtocol.prototype.readFieldBegin = function() {
   r.fid = fid;
 
   return r;
-}
+};
 
 TJSONProtocol.prototype.readFieldEnd = function() {
   var pos = this.rpos.pop();
@@ -737,7 +1524,7 @@ TJSONProtocol.prototype.readFieldEnd = function() {
   while (this.rstack.length > pos) {
     this.rstack.pop();
   }
-}
+};
 
 TJSONProtocol.prototype.readMapBegin = function() {
   var map = this.rstack.pop();
@@ -752,11 +1539,11 @@ TJSONProtocol.prototype.readMapBegin = function() {
   this.rstack.push(map.shift());
 
   return r;
-}
+};
 
 TJSONProtocol.prototype.readMapEnd = function() {
   this.readFieldEnd();
-}
+};
 
 TJSONProtocol.prototype.readListBegin = function() {
   var list = this.rstack[this.rstack.length - 1];
@@ -769,19 +1556,19 @@ TJSONProtocol.prototype.readListBegin = function() {
   this.rstack.push(list);
 
   return r;
-}
+};
 
 TJSONProtocol.prototype.readListEnd = function() {
   this.readFieldEnd();
-}
+};
 
 TJSONProtocol.prototype.readSetBegin = function() {
   return this.readListBegin();
-}
+};
 
 TJSONProtocol.prototype.readSetEnd = function() {
   return this.readListEnd();
-}
+};
 
 TJSONProtocol.prototype.readBool = function() {
   var r = this.readI32();
@@ -793,15 +1580,15 @@ TJSONProtocol.prototype.readBool = function() {
   }
 
   return r;
-}
+};
 
 TJSONProtocol.prototype.readByte = function() {
   return this.readI32();
-}
+};
 
 TJSONProtocol.prototype.readI16 = function() {
   return this.readI32();
-}
+};
 
 TJSONProtocol.prototype.readI32 = function(f) {
   if (f === undefined) {
@@ -833,31 +1620,31 @@ TJSONProtocol.prototype.readI32 = function(f) {
   }
 
   return r.value;
-}
+};
 
 TJSONProtocol.prototype.readI64 = function() {
   return new Int64(this.readI32());
-}
+};
 
 TJSONProtocol.prototype.readDouble = function() {
   return this.readI32();
-}
+};
 
 TJSONProtocol.prototype.readBinary = function() {
   return this.readString();
-}
+};
 
 TJSONProtocol.prototype.readString = function() {
   var r = this.readI32();
   return r;
-}
+};
 
 TJSONProtocol.prototype.getTransport = function() {
   return this.trans;
-}
+};
 
 //Method to arbitrarily skip over data.
 TJSONProtocol.prototype.skip = function(type) {
   throw 'skip not supported yet';
-}
+};
 

http://git-wip-us.apache.org/repos/asf/thrift/blob/20aeba3e/lib/nodejs/lib/thrift/thrift.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/lib/thrift/thrift.js b/lib/nodejs/lib/thrift/thrift.js
index 94223e3..aabe11f 100644
--- a/lib/nodejs/lib/thrift/thrift.js
+++ b/lib/nodejs/lib/thrift/thrift.js
@@ -36,19 +36,19 @@ var Type = exports.Type = {
   LIST: 15,
   UTF8: 16,
   UTF16: 17,
-}
+};
 
 exports.MessageType = {
   CALL: 1,
   REPLY: 2,
   EXCEPTION: 3,
   ONEWAY: 4,
-}
+};
 
 var TException = exports.TException = function(message) {
   Error.call(this, message);
   this.name = 'TException';
-}
+};
 util.inherits(TException, Error);
 
 var TApplicationExceptionType = exports.TApplicationExceptionType = {
@@ -63,81 +63,73 @@ var TApplicationExceptionType = exports.TApplicationExceptionType = {
   INVALID_TRANSFORM: 8,
   INVALID_PROTOCOL: 9,
   UNSUPPORTED_CLIENT_TYPE: 10
-}
+};
 
 var TApplicationException = exports.TApplicationException = function(type, message) {
   TException.call(this, message);
   this.type = type || TApplicationExceptionType.UNKNOWN;
   this.name = 'TApplicationException';
-}
+};
 util.inherits(TApplicationException, TException);
 
 TApplicationException.prototype.read = function(input) {
-  var ftype
-  var fid
-  var ret = input.readStructBegin('TApplicationException')
+  var ftype;
+  var ret = input.readStructBegin('TApplicationException');
 
   while(1){
-
-      ret = input.readFieldBegin()
-
+      ret = input.readFieldBegin();
       if(ret.ftype == Type.STOP)
-          break
-
-      var fid = ret.fid
+          break;
 
-      switch(fid){
+      switch(ret.fid){
           case 1:
               if( ret.ftype == Type.STRING ){
-                  ret = input.readString()
-                  this.message = ret
+                  ret = input.readString();
+                  this.message = ret;
               } else {
-                  ret = input.skip(ret.ftype)
+                  ret = input.skip(ret.ftype);
               }
-
-              break
+              break;
           case 2:
               if( ret.ftype == Type.I32 ){
-                  ret = input.readI32()
-                  this.type = ret
+                  ret = input.readI32();
+                  this.type = ret;
               } else {
-                  ret   = input.skip(ret.ftype)
+                  ret   = input.skip(ret.ftype);
               }
-              break
-
+              break;
           default:
-              ret = input.skip(ret.ftype)
-              break
+              ret = input.skip(ret.ftype);
+              break;
       }
-      input.readFieldEnd()
+      input.readFieldEnd();
   }
-
-  input.readStructEnd()
-}
+  input.readStructEnd();
+};
 
 TApplicationException.prototype.write = function(output){
   output.writeStructBegin('TApplicationException');
 
   if (this.message) {
-      output.writeFieldBegin('message', Type.STRING, 1)
-      output.writeString(this.message)
-      output.writeFieldEnd()
+      output.writeFieldBegin('message', Type.STRING, 1);
+      output.writeString(this.message);
+      output.writeFieldEnd();
   }
 
   if (this.code) {
-      output.writeFieldBegin('type', Type.I32, 2)
-      output.writeI32(this.code)
-      output.writeFieldEnd()
+      output.writeFieldBegin('type', Type.I32, 2);
+      output.writeI32(this.code);
+      output.writeFieldEnd();
   }
 
-  output.writeFieldStop()
-  output.writeStructEnd()
-}
+  output.writeFieldStop();
+  output.writeStructEnd();
+};
 
 exports.objectLength = function(obj) {
   return Object.keys(obj).length;
-}
+};
 
 exports.inherits = function(constructor, superConstructor) {
   util.inherits(constructor, superConstructor);
-}
+};

http://git-wip-us.apache.org/repos/asf/thrift/blob/20aeba3e/lib/nodejs/lib/thrift/transport.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/lib/thrift/transport.js b/lib/nodejs/lib/thrift/transport.js
index 2926d00..8423f89 100644
--- a/lib/nodejs/lib/thrift/transport.js
+++ b/lib/nodejs/lib/thrift/transport.js
@@ -169,7 +169,7 @@ TFramedTransport.prototype = {
     if (this.onFlush) {
       // TODO: optimize this better, allocate one buffer instead of both:
       var msg = new Buffer(out.length + 4);
-      binary.writeI32(msg, out.length)
+      binary.writeI32(msg, out.length);
       frameLeft = binary.readI32(this.inBuf, 0);
       out.copy(msg, 4, 0, out.length);
       this.onFlush(msg);
@@ -235,7 +235,7 @@ TBufferedTransport.prototype = {
   },
 
   read: function(len) {
-    this.ensureAvailable(len)
+    this.ensureAvailable(len);
     var buf = new Buffer(len);
     this.inBuf.copy(buf, 0, this.readCursor, this.readCursor + len);
     this.readCursor += len;
@@ -243,33 +243,33 @@ TBufferedTransport.prototype = {
   },
 
   readByte: function() {
-    this.ensureAvailable(1)
+    this.ensureAvailable(1);
     return binary.readByte(this.inBuf[this.readCursor++]);
   },
 
   readI16: function() {
-    this.ensureAvailable(2)
+    this.ensureAvailable(2);
     var i16 = binary.readI16(this.inBuf, this.readCursor);
     this.readCursor += 2;
     return i16;
   },
 
   readI32: function() {
-    this.ensureAvailable(4)
+    this.ensureAvailable(4);
     var i32 = binary.readI32(this.inBuf, this.readCursor);
     this.readCursor += 4;
     return i32;
   },
 
   readDouble: function() {
-    this.ensureAvailable(8)
+    this.ensureAvailable(8);
     var d = binary.readDouble(this.inBuf, this.readCursor);
     this.readCursor += 8;
     return d;
   },
 
   readString: function(len) {
-    this.ensureAvailable(len)
+    this.ensureAvailable(len);
     var str = this.inBuf.toString('utf8', this.readCursor, this.readCursor + len);
     this.readCursor += len;
     return str;

http://git-wip-us.apache.org/repos/asf/thrift/blob/20aeba3e/lib/nodejs/test/client.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/test/client.js b/lib/nodejs/test/client.js
index 8813f91..d57676e 100644
--- a/lib/nodejs/test/client.js
+++ b/lib/nodejs/test/client.js
@@ -41,6 +41,8 @@ program
 var protocol = thrift.TBinaryProtocol;
 if (program.protocol === "json") {
   protocol = thrift.TJSONProtocol;
+} else if (program.protocol === "compact") {
+  protocol = thrift.TCompactProtocol;
 } 
 
 var transport =  thrift.TBufferedTransport;

http://git-wip-us.apache.org/repos/asf/thrift/blob/20aeba3e/lib/nodejs/test/server.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/test/server.js b/lib/nodejs/test/server.js
index 605c700..6afff07 100644
--- a/lib/nodejs/test/server.js
+++ b/lib/nodejs/test/server.js
@@ -41,6 +41,8 @@ if (program.transport === "framed") {
 var protocol = thrift.TBinaryProtocol;
 if (program.protocol === "json") {
   protocol = thrift.TJSONProtocol;
+} else if (program.protocol === "compact") {
+  protocol = thrift.TCompactProtocol;
 } 
 
 var handler = ThriftTestHandler;

http://git-wip-us.apache.org/repos/asf/thrift/blob/20aeba3e/lib/nodejs/test/testAll.sh
----------------------------------------------------------------------
diff --git a/lib/nodejs/test/testAll.sh b/lib/nodejs/test/testAll.sh
index 9d1da3f..41c33cf 100755
--- a/lib/nodejs/test/testAll.sh
+++ b/lib/nodejs/test/testAll.sh
@@ -73,6 +73,8 @@ node ${DIR}/binary.test.js || TESTOK=1
 #integration tests
 
 #TCP connection tests
+testClientServer compact buffered || TESTOK=1
+testClientServer compact framed || TESTOK=1
 testClientServer binary buffered || TESTOK=1
 testClientServer json buffered || TESTOK=1
 testClientServer binary framed || TESTOK=1
@@ -82,7 +84,7 @@ testClientServer json framed || TESTOK=1
 testMultiplexedClientServer binary buffered || TESTOK=1
 testMultiplexedClientServer json buffered || TESTOK=1
 testMultiplexedClientServer binary framed || TESTOK=1
-testMultiplexedClientServer json framed || TESTOK=1
+testMultiplexedClientServer compact framed || TESTOK=1
 
 #test ssl connection
 testClientServer binary framed --ssl || TESTOK=1
@@ -90,8 +92,11 @@ testMultiplexedClientServer binary framed --ssl || TESTOK=1
 
 #test promise style
 testClientServer binary framed --promise || TESTOK=1
+testClientServer compact buffered --promise || TESTOK=1
 
 #HTTP tests
+testHttpClientServer compact buffered || TESTOK=1
+testHttpClientServer compact framed || TESTOK=1
 testHttpClientServer json buffered || TESTOK=1
 testHttpClientServer json framed || TESTOK=1
 testHttpClientServer binary buffered || TESTOK=1

http://git-wip-us.apache.org/repos/asf/thrift/blob/20aeba3e/lib/nodejs/test/thrift_test_driver.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/test/thrift_test_driver.js b/lib/nodejs/test/thrift_test_driver.js
index 02613ec..b1d744b 100644
--- a/lib/nodejs/test/thrift_test_driver.js
+++ b/lib/nodejs/test/thrift_test_driver.js
@@ -146,11 +146,21 @@ client.testI64(-5, function(err, response) {
   assert.equal(-5, response);
 });
 
+client.testI64(734359738368, function(err, response) {
+  assert( ! err);
+  assert.equal(734359738368, response);
+});
+
 client.testI64(-34359738368, function(err, response) {
   assert( ! err);
   assert.equal(-34359738368, response);
 });
 
+client.testI64(-734359738368, function(err, response) {
+  assert( ! err);
+  assert.equal(-734359738368, response);
+});
+
 client.testDouble(-5.2098523, function(err, response) {
   assert( ! err);
   assert.equal(-5.2098523, response);
@@ -192,21 +202,22 @@ client.testMap(mapout, function(err, response) {
 
 var mapTestInput = {
   "a":"123", "a b":"with spaces ", "same":"same", "0":"numeric key",
-  "longValue":stringTest, stringTest:"long key"
+  "longValue":stringTest, "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, ":"long key"
 };
 client.testStringMap(mapTestInput, function(err, response) {
   assert( ! err);
   assert.deepEqual(mapTestInput, response);
 });
 
-var setTestInput = [1,2,3];
-client.testSet(setTestInput, function(err, response) {
+var setTestSetInput = [1,2,3];
+client.testSet(setTestSetInput, function(err, response) {
   assert( ! err);
-  assert.deepEqual(setTestInput, response);
+  assert.deepEqual(setTestSetInput, response);
 });
-client.testList(setTestInput, function(err, response) {
+var setTestListInput = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
+client.testList(setTestListInput, function(err, response) {
   assert( ! err);
-  assert.deepEqual(setTestInput, response);
+  assert.deepEqual(setTestListInput, response);
 });
 
 client.testEnum(ttypes.Numberz.ONE, function(err, response) {
@@ -223,7 +234,7 @@ var mapMapTest = {
   "4": {"1":1, "2":2, "3":3, "4":4},
   "-4": {"-4":-4, "-3":-3, "-2":-2, "-1":-1}
 };
-client.testMapMap(mapMapTest, function(err, response) {
+client.testMapMap(1, function(err, response) {
   assert( ! err);
   assert.deepEqual(mapMapTest, response);
 });

http://git-wip-us.apache.org/repos/asf/thrift/blob/20aeba3e/lib/nodejs/test/thrift_test_driver_promise.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/test/thrift_test_driver_promise.js b/lib/nodejs/test/thrift_test_driver_promise.js
index 22e2572..22175cb 100644
--- a/lib/nodejs/test/thrift_test_driver_promise.js
+++ b/lib/nodejs/test/thrift_test_driver_promise.js
@@ -289,7 +289,7 @@ var mapMapTest = {
   "4": {"1":1, "2":2, "3":3, "4":4},
   "-4": {"-4":-4, "-3":-3, "-2":-2, "-1":-1}
 };
-client.testMapMap(mapMapTest)
+client.testMapMap(1)
   .then(function(response) {
     assert.deepEqual(mapMapTest, response);
   })