THRIFT-4436: port nodejs changes from THRIFT-3748 to js lib,
test for serialization of nested list,
run all tests when building js lib
Client: js

This closes #1457
diff --git a/lib/js/Gruntfile.js b/lib/js/Gruntfile.js
index 577a393..8264243 100644
--- a/lib/js/Gruntfile.js
+++ b/lib/js/Gruntfile.js
@@ -175,12 +175,5 @@
                               'shell:ThriftGenJQ', 'qunit:ThriftJSJQ', 'qunit:ThriftJSJQ_TLS',
                               'shell:ThriftGenES6', 'qunit:ThriftWSES6'
                              ]);
-  grunt.registerTask('default', ['jshint', 'shell:InstallThriftJS', 'shell:InstallThriftNodeJSDep', 'shell:ThriftGen',
-                                 'external_daemon:ThriftTestServer', 'external_daemon:ThriftTestServer_TLS',
-                                 'qunit:ThriftJS', 'qunit:ThriftJS_TLS',
-                                 'qunit:ThriftWS',
-                                 'shell:ThriftGenJQ', 'qunit:ThriftJSJQ', 'qunit:ThriftJSJQ_TLS',
-                                 'shell:ThriftGenES6', 'qunit:ThriftWSES6',
-                                 'concat', 'uglify', 'jsdoc'
-                                ]);
+  grunt.registerTask('default', ['test', 'concat', 'uglify', 'jsdoc']);
 };
diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js
index 5d420a2..eeae873 100644
--- a/lib/js/src/thrift.js
+++ b/lib/js/src/thrift.js
@@ -1258,7 +1258,12 @@
 
     /** Deserializes the end of a list. */
     readListEnd: function() {
-        this.readFieldEnd();
+        var pos = this.rpos.pop() - 2;
+        var st = this.rstack;
+        st.pop();
+        if (st instanceof Array && st.length > pos && st[pos].length > 0) {
+          st.push(st[pos].shift());
+        }
     },
 
     /**
diff --git a/lib/js/test/deep-constructor.test.js b/lib/js/test/deep-constructor.test.js
index 336fc15..f349e46 100644
--- a/lib/js/test/deep-constructor.test.js
+++ b/lib/js/test/deep-constructor.test.js
@@ -61,7 +61,13 @@
           DB: new Simple({value: 'k'})
         }
       ]
-    }
+    },
+
+    list_of_list_field: [
+       ['one', 'two'],
+       ['three', 'four'],
+       ['five', 'six']
+    ]
   }
   );
 }
@@ -108,7 +114,13 @@
           DB: {value: 'k'}
         }
       ]
-    }
+    },
+
+    list_of_list_field: [
+      ['one', 'two'],
+      ['three', 'four'],
+      ['five', 'six']
+   ]
   };
 }
 
@@ -125,6 +137,12 @@
     assert.equal(obj.struct_nested_containers_field[0][0].C[1].value, 'i');
     assert.equal(obj.struct_nested_containers_field2.D[0].DA.value, 'j');
     assert.equal(obj.struct_nested_containers_field2.D[1].DB.value, 'k');
+    assert.equal(obj.list_of_list_field[0][0], 'one');
+    assert.equal(obj.list_of_list_field[0][1], 'two');
+    assert.equal(obj.list_of_list_field[1][0], 'three');
+    assert.equal(obj.list_of_list_field[1][1], 'four');
+    assert.equal(obj.list_of_list_field[2][0], 'five');
+    assert.equal(obj.list_of_list_field[2][1], 'six');
 }
 
 var cases = {