THRIFT-4443: Implement skip function in json_protocol
Client: node.js

This closes #1460
diff --git a/lib/nodejs/lib/thrift/json_protocol.js b/lib/nodejs/lib/thrift/json_protocol.js
index 84c62f2..d960be9 100644
--- a/lib/nodejs/lib/thrift/json_protocol.js
+++ b/lib/nodejs/lib/thrift/json_protocol.js
@@ -738,5 +738,65 @@
  * Method to arbitrarily skip over data
  */
 TJSONProtocol.prototype.skip = function(type) {
-  throw new Error('skip not supported yet');
+    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);
+  }
 };
diff --git a/lib/nodejs/test/exceptions.js b/lib/nodejs/test/exceptions.js
index 0a75770..afb3f67 100644
--- a/lib/nodejs/test/exceptions.js
+++ b/lib/nodejs/test/exceptions.js
@@ -36,6 +36,20 @@
   assert.end();
 });
 
+test('unexpected TApplicationException ', function t(assert) {
+  var e = new thrift.TApplicationException(1, 100);
+  assert.ok(e instanceof thrift.TApplicationException, 'is instanceof TApplicationException');
+  assert.ok(e instanceof thrift.TException, 'is instanceof TException');
+  assert.ok(e instanceof Error, 'is instanceof Error');
+  assert.equal(typeof e.stack, 'string', 'has stack trace');
+  assert.ok(/^TApplicationException: 100/.test(e.stack), 'Stack trace has correct error name and message');
+  assert.ok(e.stack.indexOf('test/exceptions.js:7:11') !== -1, 'stack trace starts on correct line and column');
+  assert.equal(e.name, 'TApplicationException', 'has function name TApplicationException');
+  assert.equal(e.message, 100, 'has error message 100');
+  assert.equal(e.type, 1, 'has type 1');
+  assert.end();
+});
+
 test('TException', function t(assert) {
   var e = new thrift.TException('foo');
   assert.ok(e instanceof thrift.TException, 'is instanceof TException');