aboutsummaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorJisi Liu <jisi.liu@gmail.com>2017-07-18 15:38:30 -0700
committerJisi Liu <jisi.liu@gmail.com>2017-07-18 15:38:30 -0700
commit09354db1434859a31a3c81abebcc4018d42f2715 (patch)
treeb87c7cdc2255e6c8062ab92b4082665cd698d753 /js
parent9053033a5076f82cf18b823c31f352e95e5bfd8d (diff)
downloadprotobuf-09354db1434859a31a3c81abebcc4018d42f2715.tar.gz
protobuf-09354db1434859a31a3c81abebcc4018d42f2715.tar.bz2
protobuf-09354db1434859a31a3c81abebcc4018d42f2715.zip
Merge from Google internal for 3.4 release
Diffstat (limited to 'js')
-rw-r--r--js/binary/encoder.js8
-rw-r--r--js/binary/utils.js4
-rw-r--r--js/binary/writer.js10
-rw-r--r--js/compatibility_tests/v3.1.0/binary/arith_test.js355
-rw-r--r--js/compatibility_tests/v3.1.0/binary/decoder_test.js334
-rw-r--r--js/compatibility_tests/v3.1.0/binary/proto_test.js628
-rw-r--r--js/compatibility_tests/v3.1.0/binary/reader_test.js922
-rw-r--r--js/compatibility_tests/v3.1.0/binary/utils_test.js668
-rw-r--r--js/compatibility_tests/v3.1.0/binary/writer_test.js122
-rw-r--r--js/compatibility_tests/v3.1.0/commonjs/test6/test6.proto40
-rw-r--r--js/compatibility_tests/v3.1.0/commonjs/test7/test7.proto42
-rw-r--r--js/compatibility_tests/v3.1.0/data.proto51
-rw-r--r--js/compatibility_tests/v3.1.0/debug_test.js105
-rw-r--r--js/compatibility_tests/v3.1.0/maps_test.js301
-rw-r--r--js/compatibility_tests/v3.1.0/message_test.js1037
-rw-r--r--js/compatibility_tests/v3.1.0/proto3_test.js329
-rw-r--r--js/compatibility_tests/v3.1.0/proto3_test.proto89
-rw-r--r--js/compatibility_tests/v3.1.0/test.proto262
-rw-r--r--js/compatibility_tests/v3.1.0/test2.proto54
-rw-r--r--js/compatibility_tests/v3.1.0/test3.proto53
-rw-r--r--js/compatibility_tests/v3.1.0/test4.proto42
-rw-r--r--js/compatibility_tests/v3.1.0/test5.proto44
-rw-r--r--js/compatibility_tests/v3.1.0/testbinary.proto212
-rw-r--r--js/compatibility_tests/v3.1.0/testempty.proto34
-rw-r--r--js/message.js86
-rw-r--r--js/message_test.js18
-rw-r--r--js/proto3_test.proto1
-rw-r--r--js/test.proto8
28 files changed, 5801 insertions, 58 deletions
diff --git a/js/binary/encoder.js b/js/binary/encoder.js
index f25935f1..8e9f5bbc 100644
--- a/js/binary/encoder.js
+++ b/js/binary/encoder.js
@@ -390,11 +390,13 @@ jspb.BinaryEncoder.prototype.writeDouble = function(value) {
/**
- * Writes a boolean value to the buffer as a varint.
- * @param {boolean} value The value to write.
+ * Writes a boolean value to the buffer as a varint. We allow numbers as input
+ * because the JSPB code generator uses 0/1 instead of true/false to save space
+ * in the string representation of the proto.
+ * @param {boolean|number} value The value to write.
*/
jspb.BinaryEncoder.prototype.writeBool = function(value) {
- goog.asserts.assert(goog.isBoolean(value));
+ goog.asserts.assert(goog.isBoolean(value) || goog.isNumber(value));
this.buffer_.push(value ? 1 : 0);
};
diff --git a/js/binary/utils.js b/js/binary/utils.js
index 7702020b..25131b06 100644
--- a/js/binary/utils.js
+++ b/js/binary/utils.js
@@ -970,10 +970,6 @@ jspb.utils.byteSourceToUint8Array = function(data) {
return /** @type {!Uint8Array} */(new Uint8Array(data));
}
- if (data.constructor === Buffer) {
- return /** @type {!Uint8Array} */(new Uint8Array(data));
- }
-
if (data.constructor === Array) {
data = /** @type {!Array.<number>} */(data);
return /** @type {!Uint8Array} */(new Uint8Array(data));
diff --git a/js/binary/writer.js b/js/binary/writer.js
index 672e94bd..037e92b2 100644
--- a/js/binary/writer.js
+++ b/js/binary/writer.js
@@ -235,7 +235,7 @@ jspb.BinaryWriter.prototype.getResultBuffer = function() {
/**
- * Converts the encoded data into a bas64-encoded string.
+ * Converts the encoded data into a base64-encoded string.
* @return {string}
*/
jspb.BinaryWriter.prototype.getResultBase64String = function() {
@@ -716,13 +716,15 @@ jspb.BinaryWriter.prototype.writeDouble = function(field, value) {
/**
- * Writes a boolean field to the buffer.
+ * Writes a boolean field to the buffer. We allow numbers as input
+ * because the JSPB code generator uses 0/1 instead of true/false to save space
+ * in the string representation of the proto.
* @param {number} field The field number.
- * @param {boolean?} value The value to write.
+ * @param {boolean?|number?} value The value to write.
*/
jspb.BinaryWriter.prototype.writeBool = function(field, value) {
if (value == null) return;
- goog.asserts.assert(goog.isBoolean(value));
+ goog.asserts.assert(goog.isBoolean(value) || goog.isNumber(value));
this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
this.encoder_.writeBool(value);
};
diff --git a/js/compatibility_tests/v3.1.0/binary/arith_test.js b/js/compatibility_tests/v3.1.0/binary/arith_test.js
new file mode 100644
index 00000000..89796bf7
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/binary/arith_test.js
@@ -0,0 +1,355 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/**
+ * @fileoverview Test cases for Int64-manipulation functions.
+ *
+ * Test suite is written using Jasmine -- see http://jasmine.github.io/
+ *
+ * @author cfallin@google.com (Chris Fallin)
+ */
+
+goog.require('goog.testing.asserts');
+goog.require('jspb.arith.Int64');
+goog.require('jspb.arith.UInt64');
+
+
+describe('binaryArithTest', function() {
+ /**
+ * Tests comparison operations.
+ */
+ it('testCompare', function() {
+ var a = new jspb.arith.UInt64(1234, 5678);
+ var b = new jspb.arith.UInt64(1234, 5678);
+ assertEquals(a.cmp(b), 0);
+ assertEquals(b.cmp(a), 0);
+ b.lo -= 1;
+ assertEquals(a.cmp(b), 1);
+ assertEquals(b.cmp(a), -1);
+ b.lo += 2;
+ assertEquals(a.cmp(b), -1);
+ assertEquals(b.cmp(a), 1);
+ b.lo = a.lo;
+ b.hi = a.hi - 1;
+ assertEquals(a.cmp(b), 1);
+ assertEquals(b.cmp(a), -1);
+
+ assertEquals(a.zero(), false);
+ assertEquals(a.msb(), false);
+ assertEquals(a.lsb(), false);
+ a.hi = 0;
+ a.lo = 0;
+ assertEquals(a.zero(), true);
+ a.hi = 0x80000000;
+ assertEquals(a.zero(), false);
+ assertEquals(a.msb(), true);
+ a.lo = 0x00000001;
+ assertEquals(a.lsb(), true);
+ });
+
+
+ /**
+ * Tests shifts.
+ */
+ it('testShifts', function() {
+ var a = new jspb.arith.UInt64(1, 0);
+ assertEquals(a.lo, 1);
+ assertEquals(a.hi, 0);
+ var orig = a;
+ a = a.leftShift();
+ assertEquals(orig.lo, 1); // original unmodified.
+ assertEquals(orig.hi, 0);
+ assertEquals(a.lo, 2);
+ assertEquals(a.hi, 0);
+ a = a.leftShift();
+ assertEquals(a.lo, 4);
+ assertEquals(a.hi, 0);
+ for (var i = 0; i < 29; i++) {
+ a = a.leftShift();
+ }
+ assertEquals(a.lo, 0x80000000);
+ assertEquals(a.hi, 0);
+ a = a.leftShift();
+ assertEquals(a.lo, 0);
+ assertEquals(a.hi, 1);
+ a = a.leftShift();
+ assertEquals(a.lo, 0);
+ assertEquals(a.hi, 2);
+ a = a.rightShift();
+ a = a.rightShift();
+ assertEquals(a.lo, 0x80000000);
+ assertEquals(a.hi, 0);
+ a = a.rightShift();
+ assertEquals(a.lo, 0x40000000);
+ assertEquals(a.hi, 0);
+ });
+
+
+ /**
+ * Tests additions.
+ */
+ it('testAdd', function() {
+ var a = new jspb.arith.UInt64(/* lo = */ 0x89abcdef,
+ /* hi = */ 0x01234567);
+ var b = new jspb.arith.UInt64(/* lo = */ 0xff52ab91,
+ /* hi = */ 0x92fa2123);
+ // Addition with carry.
+ var c = a.add(b);
+ assertEquals(a.lo, 0x89abcdef); // originals unmodified.
+ assertEquals(a.hi, 0x01234567);
+ assertEquals(b.lo, 0xff52ab91);
+ assertEquals(b.hi, 0x92fa2123);
+ assertEquals(c.lo, 0x88fe7980);
+ assertEquals(c.hi, 0x941d668b);
+
+ // Simple addition without carry.
+ a.lo = 2;
+ a.hi = 0;
+ b.lo = 3;
+ b.hi = 0;
+ c = a.add(b);
+ assertEquals(c.lo, 5);
+ assertEquals(c.hi, 0);
+ });
+
+
+ /**
+ * Test subtractions.
+ */
+ it('testSub', function() {
+ var kLength = 10;
+ var hiValues = [0x1682ef32,
+ 0x583902f7,
+ 0xb62f5955,
+ 0x6ea99bbf,
+ 0x25a39c20,
+ 0x0700a08b,
+ 0x00f7304d,
+ 0x91a5b5af,
+ 0x89077fd2,
+ 0xe09e347c];
+ var loValues = [0xe1538b18,
+ 0xbeacd556,
+ 0x74100758,
+ 0x96e3cb26,
+ 0x56c37c3f,
+ 0xe00b3f7d,
+ 0x859f25d7,
+ 0xc2ee614a,
+ 0xe1d21cd7,
+ 0x30aae6a4];
+ for (var i = 0; i < kLength; i++) {
+ for (var j = 0; j < kLength; j++) {
+ var a = new jspb.arith.UInt64(loValues[i], hiValues[j]);
+ var b = new jspb.arith.UInt64(loValues[j], hiValues[i]);
+ var c = a.add(b).sub(b);
+ assertEquals(c.hi, a.hi);
+ assertEquals(c.lo, a.lo);
+ }
+ }
+ });
+
+
+ /**
+ * Tests 32-by-32 multiplication.
+ */
+ it('testMul32x32', function() {
+ var testData = [
+ // a b low(a*b) high(a*b)
+ [0xc0abe2f8, 0x1607898a, 0x5de711b0, 0x109471b8],
+ [0x915eb3cb, 0x4fb66d0e, 0xbd0d441a, 0x2d43d0bc],
+ [0xfe4efe70, 0x80b48c37, 0xbcddea10, 0x7fdada0c],
+ [0xe222fd4a, 0xe43d524a, 0xd5e0eb64, 0xc99d549c],
+ [0xd171f469, 0xb94ebd01, 0x4be17969, 0x979bc4fa],
+ [0x829cc1df, 0xe2598b38, 0xf4157dc8, 0x737c12ad],
+ [0xf10c3767, 0x8382881e, 0x942b3612, 0x7bd428b8],
+ [0xb0f6dd24, 0x232597e1, 0x079c98a4, 0x184bbce7],
+ [0xfcdb05a7, 0x902f55bc, 0x636199a4, 0x8e69f412],
+ [0x0dd0bfa9, 0x916e27b1, 0x6e2542d9, 0x07d92e65]
+ ];
+
+ for (var i = 0; i < testData.length; i++) {
+ var a = testData[i][0] >>> 0;
+ var b = testData[i][1] >>> 0;
+ var cLow = testData[i][2] >>> 0;
+ var cHigh = testData[i][3] >>> 0;
+ var c = jspb.arith.UInt64.mul32x32(a, b);
+ assertEquals(c.lo, cLow);
+ assertEquals(c.hi, cHigh);
+ }
+ });
+
+
+ /**
+ * Tests 64-by-32 multiplication.
+ */
+ it('testMul', function() {
+ // 64x32 bits produces 96 bits of product. The multiplication function under
+ // test truncates the top 32 bits, so we compare against a 64-bit expected
+ // product.
+ var testData = [
+ // low(a) high(a) low(a*b) high(a*b)
+ [0xec10955b, 0x360eb168, 0x4b7f3f5b, 0xbfcb7c59, 0x9517da5f],
+ [0x42b000fc, 0x9d101642, 0x6fa1ab72, 0x2584c438, 0x6a9e6d2b],
+ [0xf42d4fb4, 0xae366403, 0xa65a1000, 0x92434000, 0x1ff978df],
+ [0x17e2f56b, 0x25487693, 0xf13f98c7, 0x73794e2d, 0xa96b0c6a],
+ [0x492f241f, 0x76c0eb67, 0x7377ac44, 0xd4336c3c, 0xfc4b1ebe],
+ [0xd6b92321, 0xe184fa48, 0xd6e76904, 0x93141584, 0xcbf44da1],
+ [0x4bf007ea, 0x968c0a9e, 0xf5e4026a, 0x4fdb1ae4, 0x61b9fb7d],
+ [0x10a83be7, 0x2d685ba6, 0xc9e5fb7f, 0x2ad43499, 0x3742473d],
+ [0x2f261829, 0x1aca681a, 0x3d3494e3, 0x8213205b, 0x283719f8],
+ [0xe4f2ce21, 0x2e74b7bd, 0xd801b38b, 0xbc17feeb, 0xc6c44e0f]
+ ];
+
+ for (var i = 0; i < testData.length; i++) {
+ var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]);
+ var prod = a.mul(testData[i][2]);
+ assertEquals(prod.lo, testData[i][3]);
+ assertEquals(prod.hi, testData[i][4]);
+ }
+ });
+
+
+ /**
+ * Tests 64-div-by-32 division.
+ */
+ it('testDiv', function() {
+ // Compute a/b, yielding quot = a/b and rem = a%b.
+ var testData = [
+ // --- divisors in (0, 2^32-1) to test full divisor range
+ // low(a) high(a) b low(quot) high(quot) rem
+ [0x712443f1, 0xe85cefcc, 0xc1a7050b, 0x332c79ad, 0x00000001, 0x92ffa882],
+ [0x11912915, 0xb2699eb5, 0x30467cbe, 0xb21b4be4, 0x00000003, 0x283465dd],
+ [0x0d917982, 0x201f2a6e, 0x3f35bf03, 0x8217c8e4, 0x00000000, 0x153402d6],
+ [0xa072c108, 0x74020c96, 0xc60568fd, 0x95f9613e, 0x00000000, 0x3f4676c2],
+ [0xd845d5d8, 0xcdd235c4, 0x20426475, 0x6154e78b, 0x00000006, 0x202fb751],
+ [0xa4dbf71f, 0x9e90465e, 0xf08e022f, 0xa8be947f, 0x00000000, 0xbe43b5ce],
+ [0x3dbe627f, 0xa791f4b9, 0x28a5bd89, 0x1f5dfe93, 0x00000004, 0x02bf9ed4],
+ [0x5c1c53ee, 0xccf5102e, 0x198576e7, 0x07e3ae31, 0x00000008, 0x02ea8fb7],
+ [0xfef1e581, 0x04714067, 0xca6540c1, 0x059e73ec, 0x00000000, 0x31658095],
+ [0x1e2dd90c, 0x13dd6667, 0x8b2184c3, 0x248d1a42, 0x00000000, 0x4ca6d0c6],
+ // --- divisors in (0, 2^16-1) to test larger quotient high-words
+ // low(a) high(a) b low(quot) high(quot) rem
+ [0x86722b47, 0x2cd57c9a, 0x00003123, 0x2ae41b7a, 0x0000e995, 0x00000f99],
+ [0x1dd7884c, 0xf5e839bc, 0x00009eeb, 0x5c886242, 0x00018c21, 0x000099b6],
+ [0x5c53d625, 0x899fc7e5, 0x000087d7, 0xd625007a, 0x0001035c, 0x000019af],
+ [0x6932d932, 0x9d0a5488, 0x000051fb, 0x9d976143, 0x0001ea63, 0x00004981],
+ [0x4d18bb85, 0x0c92fb31, 0x00001d9f, 0x03265ab4, 0x00006cac, 0x000001b9],
+ [0xbe756768, 0xdea67ccb, 0x00008a03, 0x58add442, 0x00019cff, 0x000056a2],
+ [0xe2466f9a, 0x2521f114, 0x0000c350, 0xa0c0860d, 0x000030ab, 0x0000a48a],
+ [0xf00ddad1, 0xe2f5446a, 0x00002cfc, 0x762697a6, 0x00050b96, 0x00000b69],
+ [0xa879152a, 0x0a70e0a5, 0x00007cdf, 0xb44151b3, 0x00001567, 0x0000363d],
+ [0x7179a74c, 0x46083fff, 0x0000253c, 0x4d39ba6e, 0x0001e17f, 0x00000f84]
+ ];
+
+ for (var i = 0; i < testData.length; i++) {
+ var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]);
+ var result = a.div(testData[i][2]);
+ var quotient = result[0];
+ var remainder = result[1];
+ assertEquals(quotient.lo, testData[i][3]);
+ assertEquals(quotient.hi, testData[i][4]);
+ assertEquals(remainder.lo, testData[i][5]);
+ }
+ });
+
+
+ /**
+ * Tests .toString() and .fromString().
+ */
+ it('testStrings', function() {
+ var testData = [
+ [0x5e84c935, 0xcae33d0e, '14619595947299359029'],
+ [0x62b3b8b8, 0x93480544, '10612738313170434232'],
+ [0x319bfb13, 0xc01c4172, '13843011313344445203'],
+ [0x5b8a65fb, 0xa5885b31, '11927883880638080507'],
+ [0x6bdb80f1, 0xb0d1b16b, '12741159895737008369'],
+ [0x4b82b442, 0x2e0d8c97, '3318463081876730946'],
+ [0x780d5208, 0x7d76752c, '9040542135845999112'],
+ [0x2e46800f, 0x0993778d, '690026616168284175'],
+ [0xf00a7e32, 0xcd8e3931, '14811839111111540274'],
+ [0x1baeccd6, 0x923048c4, '10533999535534820566'],
+ [0x03669d29, 0xbff3ab72, '13831587386756603177'],
+ [0x2526073e, 0x01affc81, '121593346566522686'],
+ [0xc24244e0, 0xd7f40d0e, '15561076969511732448'],
+ [0xc56a341e, 0xa68b66a7, '12000798502816461854'],
+ [0x8738d64d, 0xbfe78604, '13828168534871037517'],
+ [0x5baff03b, 0xd7572aea, '15516918227177304123'],
+ [0x4a843d8a, 0x864e132b, '9677693725920476554'],
+ [0x25b4e94d, 0x22b54dc6, '2500990681505655117'],
+ [0x6bbe664b, 0x55a5cc0e, '6171563226690381387'],
+ [0xee916c81, 0xb00aabb3, '12685140089732426881']
+ ];
+
+ for (var i = 0; i < testData.length; i++) {
+ var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]);
+ var roundtrip = jspb.arith.UInt64.fromString(a.toString());
+ assertEquals(roundtrip.lo, a.lo);
+ assertEquals(roundtrip.hi, a.hi);
+ assertEquals(a.toString(), testData[i][2]);
+ }
+ });
+
+
+ /**
+ * Tests signed Int64s. These are built on UInt64s, so we only need to test
+ * the explicit overrides: .toString() and .fromString().
+ */
+ it('testSignedInt64', function() {
+ var testStrings = [
+ '-7847499644178593666',
+ '3771946501229139523',
+ '2872856549054995060',
+ '-5780049594274350904',
+ '3383785956695105201',
+ '2973055184857072610',
+ '-3879428459215627206',
+ '4589812431064156631',
+ '8484075557333689940',
+ '1075325817098092407',
+ '-4346697501012292314',
+ '2488620459718316637',
+ '6112655187423520672',
+ '-3655278273928612104',
+ '3439154019435803196',
+ '1004112478843763757',
+ '-6587790776614368413',
+ '664320065099714586',
+ '4760412909973292912',
+ '-7911903989602274672'
+ ];
+
+ for (var i = 0; i < testStrings.length; i++) {
+ var roundtrip =
+ jspb.arith.Int64.fromString(testStrings[i]).toString();
+ assertEquals(roundtrip, testStrings[i]);
+ }
+ });
+});
diff --git a/js/compatibility_tests/v3.1.0/binary/decoder_test.js b/js/compatibility_tests/v3.1.0/binary/decoder_test.js
new file mode 100644
index 00000000..ac312648
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/binary/decoder_test.js
@@ -0,0 +1,334 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/**
+ * @fileoverview Test cases for jspb's binary protocol buffer decoder.
+ *
+ * There are two particular magic numbers that need to be pointed out -
+ * 2^64-1025 is the largest number representable as both a double and an
+ * unsigned 64-bit integer, and 2^63-513 is the largest number representable as
+ * both a double and a signed 64-bit integer.
+ *
+ * Test suite is written using Jasmine -- see http://jasmine.github.io/
+ *
+ * @author aappleby@google.com (Austin Appleby)
+ */
+
+goog.require('goog.testing.asserts');
+goog.require('jspb.BinaryConstants');
+goog.require('jspb.BinaryDecoder');
+goog.require('jspb.BinaryEncoder');
+
+
+/**
+ * Tests encoding and decoding of unsigned types.
+ * @param {Function} readValue
+ * @param {Function} writeValue
+ * @param {number} epsilon
+ * @param {number} upperLimit
+ * @param {Function} filter
+ * @suppress {missingProperties|visibility}
+ */
+function doTestUnsignedValue(readValue,
+ writeValue, epsilon, upperLimit, filter) {
+ var encoder = new jspb.BinaryEncoder();
+
+ // Encode zero and limits.
+ writeValue.call(encoder, filter(0));
+ writeValue.call(encoder, filter(epsilon));
+ writeValue.call(encoder, filter(upperLimit));
+
+ // Encode positive values.
+ for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+ writeValue.call(encoder, filter(cursor));
+ }
+
+ var decoder = jspb.BinaryDecoder.alloc(encoder.end());
+
+ // Check zero and limits.
+ assertEquals(filter(0), readValue.call(decoder));
+ assertEquals(filter(epsilon), readValue.call(decoder));
+ assertEquals(filter(upperLimit), readValue.call(decoder));
+
+ // Check positive values.
+ for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+ if (filter(cursor) != readValue.call(decoder)) throw 'fail!';
+ }
+
+ // Encoding values outside the valid range should assert.
+ assertThrows(function() {writeValue.call(encoder, -1);});
+ assertThrows(function() {writeValue.call(encoder, upperLimit * 1.1);});
+}
+
+
+/**
+ * Tests encoding and decoding of signed types.
+ * @param {Function} readValue
+ * @param {Function} writeValue
+ * @param {number} epsilon
+ * @param {number} lowerLimit
+ * @param {number} upperLimit
+ * @param {Function} filter
+ * @suppress {missingProperties}
+ */
+function doTestSignedValue(readValue,
+ writeValue, epsilon, lowerLimit, upperLimit, filter) {
+ var encoder = new jspb.BinaryEncoder();
+
+ // Encode zero and limits.
+ writeValue.call(encoder, filter(lowerLimit));
+ writeValue.call(encoder, filter(-epsilon));
+ writeValue.call(encoder, filter(0));
+ writeValue.call(encoder, filter(epsilon));
+ writeValue.call(encoder, filter(upperLimit));
+
+ var inputValues = [];
+
+ // Encode negative values.
+ for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) {
+ var val = filter(cursor);
+ writeValue.call(encoder, val);
+ inputValues.push(val);
+ }
+
+ // Encode positive values.
+ for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+ var val = filter(cursor);
+ writeValue.call(encoder, val);
+ inputValues.push(val);
+ }
+
+ var decoder = jspb.BinaryDecoder.alloc(encoder.end());
+
+ // Check zero and limits.
+ assertEquals(filter(lowerLimit), readValue.call(decoder));
+ assertEquals(filter(-epsilon), readValue.call(decoder));
+ assertEquals(filter(0), readValue.call(decoder));
+ assertEquals(filter(epsilon), readValue.call(decoder));
+ assertEquals(filter(upperLimit), readValue.call(decoder));
+
+ // Verify decoded values.
+ for (var i = 0; i < inputValues.length; i++) {
+ assertEquals(inputValues[i], readValue.call(decoder));
+ }
+
+ // Encoding values outside the valid range should assert.
+ assertThrows(function() {writeValue.call(encoder, lowerLimit * 1.1);});
+ assertThrows(function() {writeValue.call(encoder, upperLimit * 1.1);});
+}
+
+describe('binaryDecoderTest', function() {
+ /**
+ * Tests the decoder instance cache.
+ */
+ it('testInstanceCache', /** @suppress {visibility} */ function() {
+ // Empty the instance caches.
+ jspb.BinaryDecoder.instanceCache_ = [];
+
+ // Allocating and then freeing a decoder should put it in the instance
+ // cache.
+ jspb.BinaryDecoder.alloc().free();
+
+ assertEquals(1, jspb.BinaryDecoder.instanceCache_.length);
+
+ // Allocating and then freeing three decoders should leave us with three in
+ // the cache.
+
+ var decoder1 = jspb.BinaryDecoder.alloc();
+ var decoder2 = jspb.BinaryDecoder.alloc();
+ var decoder3 = jspb.BinaryDecoder.alloc();
+ decoder1.free();
+ decoder2.free();
+ decoder3.free();
+
+ assertEquals(3, jspb.BinaryDecoder.instanceCache_.length);
+ });
+
+
+ /**
+ * Tests reading 64-bit integers as hash strings.
+ */
+ it('testHashStrings', function() {
+ var encoder = new jspb.BinaryEncoder();
+
+ var hashA = String.fromCharCode(0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00);
+ var hashB = String.fromCharCode(0x12, 0x34, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00);
+ var hashC = String.fromCharCode(0x12, 0x34, 0x56, 0x78,
+ 0x87, 0x65, 0x43, 0x21);
+ var hashD = String.fromCharCode(0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF);
+
+ encoder.writeVarintHash64(hashA);
+ encoder.writeVarintHash64(hashB);
+ encoder.writeVarintHash64(hashC);
+ encoder.writeVarintHash64(hashD);
+
+ encoder.writeFixedHash64(hashA);
+ encoder.writeFixedHash64(hashB);
+ encoder.writeFixedHash64(hashC);
+ encoder.writeFixedHash64(hashD);
+
+ var decoder = jspb.BinaryDecoder.alloc(encoder.end());
+
+ assertEquals(hashA, decoder.readVarintHash64());
+ assertEquals(hashB, decoder.readVarintHash64());
+ assertEquals(hashC, decoder.readVarintHash64());
+ assertEquals(hashD, decoder.readVarintHash64());
+
+ assertEquals(hashA, decoder.readFixedHash64());
+ assertEquals(hashB, decoder.readFixedHash64());
+ assertEquals(hashC, decoder.readFixedHash64());
+ assertEquals(hashD, decoder.readFixedHash64());
+ });
+
+
+ /**
+ * Verifies that misuse of the decoder class triggers assertions.
+ * @suppress {checkTypes|visibility}
+ */
+ it('testDecodeErrors', function() {
+ // Reading a value past the end of the stream should trigger an assertion.
+ var decoder = jspb.BinaryDecoder.alloc([0, 1, 2]);
+ assertThrows(function() {decoder.readUint64()});
+
+ // Overlong varints should trigger assertions.
+ decoder.setBlock([255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 0]);
+ assertThrows(function() {decoder.readUnsignedVarint64()});
+ decoder.reset();
+ assertThrows(function() {decoder.readSignedVarint64()});
+ decoder.reset();
+ assertThrows(function() {decoder.readZigzagVarint64()});
+
+ // Positive 32-bit varints encoded with 1 bits in positions 33 through 35
+ // should trigger assertions.
+ decoder.setBlock([255, 255, 255, 255, 0x1F]);
+ assertThrows(function() {decoder.readUnsignedVarint32()});
+
+ decoder.setBlock([255, 255, 255, 255, 0x2F]);
+ assertThrows(function() {decoder.readUnsignedVarint32()});
+
+ decoder.setBlock([255, 255, 255, 255, 0x4F]);
+ assertThrows(function() {decoder.readUnsignedVarint32()});
+
+ // Negative 32-bit varints encoded with non-1 bits in the high dword should
+ // trigger assertions.
+ decoder.setBlock([255, 255, 255, 255, 255, 255, 0, 255, 255, 1]);
+ assertThrows(function() {decoder.readUnsignedVarint32()});
+
+ decoder.setBlock([255, 255, 255, 255, 255, 255, 255, 255, 255, 0]);
+ assertThrows(function() {decoder.readUnsignedVarint32()});
+ });
+
+
+ /**
+ * Tests encoding and decoding of unsigned integers.
+ */
+ it('testUnsignedIntegers', function() {
+ doTestUnsignedValue(
+ jspb.BinaryDecoder.prototype.readUint8,
+ jspb.BinaryEncoder.prototype.writeUint8,
+ 1, 0xFF, Math.round);
+
+ doTestUnsignedValue(
+ jspb.BinaryDecoder.prototype.readUint16,
+ jspb.BinaryEncoder.prototype.writeUint16,
+ 1, 0xFFFF, Math.round);
+
+ doTestUnsignedValue(
+ jspb.BinaryDecoder.prototype.readUint32,
+ jspb.BinaryEncoder.prototype.writeUint32,
+ 1, 0xFFFFFFFF, Math.round);
+
+ doTestUnsignedValue(
+ jspb.BinaryDecoder.prototype.readUint64,
+ jspb.BinaryEncoder.prototype.writeUint64,
+ 1, Math.pow(2, 64) - 1025, Math.round);
+ });
+
+
+ /**
+ * Tests encoding and decoding of signed integers.
+ */
+ it('testSignedIntegers', function() {
+ doTestSignedValue(
+ jspb.BinaryDecoder.prototype.readInt8,
+ jspb.BinaryEncoder.prototype.writeInt8,
+ 1, -0x80, 0x7F, Math.round);
+
+ doTestSignedValue(
+ jspb.BinaryDecoder.prototype.readInt16,
+ jspb.BinaryEncoder.prototype.writeInt16,
+ 1, -0x8000, 0x7FFF, Math.round);
+
+ doTestSignedValue(
+ jspb.BinaryDecoder.prototype.readInt32,
+ jspb.BinaryEncoder.prototype.writeInt32,
+ 1, -0x80000000, 0x7FFFFFFF, Math.round);
+
+ doTestSignedValue(
+ jspb.BinaryDecoder.prototype.readInt64,
+ jspb.BinaryEncoder.prototype.writeInt64,
+ 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+ });
+
+
+ /**
+ * Tests encoding and decoding of floats.
+ */
+ it('testFloats', function() {
+ /**
+ * @param {number} x
+ * @return {number}
+ */
+ function truncate(x) {
+ var temp = new Float32Array(1);
+ temp[0] = x;
+ return temp[0];
+ }
+ doTestSignedValue(
+ jspb.BinaryDecoder.prototype.readFloat,
+ jspb.BinaryEncoder.prototype.writeFloat,
+ jspb.BinaryConstants.FLOAT32_EPS,
+ -jspb.BinaryConstants.FLOAT32_MAX,
+ jspb.BinaryConstants.FLOAT32_MAX,
+ truncate);
+
+ doTestSignedValue(
+ jspb.BinaryDecoder.prototype.readDouble,
+ jspb.BinaryEncoder.prototype.writeDouble,
+ jspb.BinaryConstants.FLOAT64_EPS * 10,
+ -jspb.BinaryConstants.FLOAT64_MAX,
+ jspb.BinaryConstants.FLOAT64_MAX,
+ function(x) { return x; });
+ });
+});
diff --git a/js/compatibility_tests/v3.1.0/binary/proto_test.js b/js/compatibility_tests/v3.1.0/binary/proto_test.js
new file mode 100644
index 00000000..26e1d30f
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/binary/proto_test.js
@@ -0,0 +1,628 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test suite is written using Jasmine -- see http://jasmine.github.io/
+
+goog.require('goog.crypt.base64');
+goog.require('goog.testing.asserts');
+goog.require('jspb.Message');
+
+// CommonJS-LoadFromFile: ../testbinary_pb proto.jspb.test
+goog.require('proto.jspb.test.ExtendsWithMessage');
+goog.require('proto.jspb.test.ForeignEnum');
+goog.require('proto.jspb.test.ForeignMessage');
+goog.require('proto.jspb.test.TestAllTypes');
+goog.require('proto.jspb.test.TestExtendable');
+goog.require('proto.jspb.test.extendOptionalBool');
+goog.require('proto.jspb.test.extendOptionalBytes');
+goog.require('proto.jspb.test.extendOptionalDouble');
+goog.require('proto.jspb.test.extendOptionalFixed32');
+goog.require('proto.jspb.test.extendOptionalFixed64');
+goog.require('proto.jspb.test.extendOptionalFloat');
+goog.require('proto.jspb.test.extendOptionalForeignEnum');
+goog.require('proto.jspb.test.extendOptionalInt32');
+goog.require('proto.jspb.test.extendOptionalInt64');
+goog.require('proto.jspb.test.extendOptionalSfixed32');
+goog.require('proto.jspb.test.extendOptionalSfixed64');
+goog.require('proto.jspb.test.extendOptionalSint32');
+goog.require('proto.jspb.test.extendOptionalSint64');
+goog.require('proto.jspb.test.extendOptionalString');
+goog.require('proto.jspb.test.extendOptionalUint32');
+goog.require('proto.jspb.test.extendOptionalUint64');
+goog.require('proto.jspb.test.extendPackedRepeatedBoolList');
+goog.require('proto.jspb.test.extendPackedRepeatedDoubleList');
+goog.require('proto.jspb.test.extendPackedRepeatedFixed32List');
+goog.require('proto.jspb.test.extendPackedRepeatedFixed64List');
+goog.require('proto.jspb.test.extendPackedRepeatedFloatList');
+goog.require('proto.jspb.test.extendPackedRepeatedForeignEnumList');
+goog.require('proto.jspb.test.extendPackedRepeatedInt32List');
+goog.require('proto.jspb.test.extendPackedRepeatedInt64List');
+goog.require('proto.jspb.test.extendPackedRepeatedSfixed32List');
+goog.require('proto.jspb.test.extendPackedRepeatedSfixed64List');
+goog.require('proto.jspb.test.extendPackedRepeatedSint32List');
+goog.require('proto.jspb.test.extendPackedRepeatedSint64List');
+goog.require('proto.jspb.test.extendPackedRepeatedUint32List');
+goog.require('proto.jspb.test.extendPackedRepeatedUint64List');
+goog.require('proto.jspb.test.extendRepeatedBoolList');
+goog.require('proto.jspb.test.extendRepeatedBytesList');
+goog.require('proto.jspb.test.extendRepeatedDoubleList');
+goog.require('proto.jspb.test.extendRepeatedFixed32List');
+goog.require('proto.jspb.test.extendRepeatedFixed64List');
+goog.require('proto.jspb.test.extendRepeatedFloatList');
+goog.require('proto.jspb.test.extendRepeatedForeignEnumList');
+goog.require('proto.jspb.test.extendRepeatedInt32List');
+goog.require('proto.jspb.test.extendRepeatedInt64List');
+goog.require('proto.jspb.test.extendRepeatedSfixed32List');
+goog.require('proto.jspb.test.extendRepeatedSfixed64List');
+goog.require('proto.jspb.test.extendRepeatedSint32List');
+goog.require('proto.jspb.test.extendRepeatedSint64List');
+goog.require('proto.jspb.test.extendRepeatedStringList');
+goog.require('proto.jspb.test.extendRepeatedUint32List');
+goog.require('proto.jspb.test.extendRepeatedUint64List');
+
+
+var suite = {};
+
+var BYTES = new Uint8Array([1, 2, 8, 9]);
+
+var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES);
+
+
+/**
+ * Helper: fill all fields on a TestAllTypes message.
+ * @param {proto.jspb.test.TestAllTypes} msg
+ */
+function fillAllFields(msg) {
+ msg.setOptionalInt32(-42);
+ // can be exactly represented by JS number (64-bit double, i.e., 52-bit
+ // mantissa).
+ msg.setOptionalInt64(-0x7fffffff00000000);
+ msg.setOptionalUint32(0x80000000);
+ msg.setOptionalUint64(0xf000000000000000);
+ msg.setOptionalSint32(-100);
+ msg.setOptionalSint64(-0x8000000000000000);
+ msg.setOptionalFixed32(1234);
+ msg.setOptionalFixed64(0x1234567800000000);
+ msg.setOptionalSfixed32(-1234);
+ msg.setOptionalSfixed64(-0x1234567800000000);
+ msg.setOptionalFloat(1.5);
+ msg.setOptionalDouble(-1.5);
+ msg.setOptionalBool(true);
+ msg.setOptionalString('hello world');
+ msg.setOptionalBytes(BYTES);
+ msg.setOptionalGroup(new proto.jspb.test.TestAllTypes.OptionalGroup());
+ msg.getOptionalGroup().setA(100);
+ var submsg = new proto.jspb.test.ForeignMessage();
+ submsg.setC(16);
+ msg.setOptionalForeignMessage(submsg);
+ msg.setOptionalForeignEnum(proto.jspb.test.ForeignEnum.FOREIGN_FOO);
+ msg.setOneofString('oneof');
+
+
+ msg.setRepeatedInt32List([-42]);
+ msg.setRepeatedInt64List([-0x7fffffff00000000]);
+ msg.setRepeatedUint32List([0x80000000]);
+ msg.setRepeatedUint64List([0xf000000000000000]);
+ msg.setRepeatedSint32List([-100]);
+ msg.setRepeatedSint64List([-0x8000000000000000]);
+ msg.setRepeatedFixed32List([1234]);
+ msg.setRepeatedFixed64List([0x1234567800000000]);
+ msg.setRepeatedSfixed32List([-1234]);
+ msg.setRepeatedSfixed64List([-0x1234567800000000]);
+ msg.setRepeatedFloatList([1.5]);
+ msg.setRepeatedDoubleList([-1.5]);
+ msg.setRepeatedBoolList([true]);
+ msg.setRepeatedStringList(['hello world']);
+ msg.setRepeatedBytesList([BYTES, BYTES]);
+ msg.setRepeatedGroupList([new proto.jspb.test.TestAllTypes.RepeatedGroup()]);
+ msg.getRepeatedGroupList()[0].setA(100);
+ submsg = new proto.jspb.test.ForeignMessage();
+ submsg.setC(1000);
+ msg.setRepeatedForeignMessageList([submsg]);
+ msg.setRepeatedForeignEnumList([proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+ msg.setPackedRepeatedInt32List([-42]);
+ msg.setPackedRepeatedInt64List([-0x7fffffff00000000]);
+ msg.setPackedRepeatedUint32List([0x80000000]);
+ msg.setPackedRepeatedUint64List([0xf000000000000000]);
+ msg.setPackedRepeatedSint32List([-100]);
+ msg.setPackedRepeatedSint64List([-0x8000000000000000]);
+ msg.setPackedRepeatedFixed32List([1234]);
+ msg.setPackedRepeatedFixed64List([0x1234567800000000]);
+ msg.setPackedRepeatedSfixed32List([-1234]);
+ msg.setPackedRepeatedSfixed64List([-0x1234567800000000]);
+ msg.setPackedRepeatedFloatList([1.5]);
+ msg.setPackedRepeatedDoubleList([-1.5]);
+ msg.setPackedRepeatedBoolList([true]);
+
+}
+
+
+/**
+ * Helper: compare a bytes field to an expected value
+ * @param {Uint8Array|string} arr
+ * @param {Uint8Array} expected
+ * @return {boolean}
+ */
+function bytesCompare(arr, expected) {
+ if (goog.isString(arr)) {
+ arr = goog.crypt.base64.decodeStringToUint8Array(arr);
+ }
+ if (arr.length != expected.length) {
+ return false;
+ }
+ for (var i = 0; i < arr.length; i++) {
+ if (arr[i] != expected[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+/**
+ * Helper: verify contents of given TestAllTypes message as set by
+ * fillAllFields().
+ * @param {proto.jspb.test.TestAllTypes} original
+ * @param {proto.jspb.test.TestAllTypes} copy
+ */
+function checkAllFields(original, copy) {
+ assertTrue(jspb.Message.equals(original, copy));
+
+ assertEquals(copy.getOptionalInt32(), -42);
+ assertEquals(copy.getOptionalInt64(), -0x7fffffff00000000);
+ assertEquals(copy.getOptionalUint32(), 0x80000000);
+ assertEquals(copy.getOptionalUint64(), 0xf000000000000000);
+ assertEquals(copy.getOptionalSint32(), -100);
+ assertEquals(copy.getOptionalSint64(), -0x8000000000000000);
+ assertEquals(copy.getOptionalFixed32(), 1234);
+ assertEquals(copy.getOptionalFixed64(), 0x1234567800000000);
+ assertEquals(copy.getOptionalSfixed32(), -1234);
+ assertEquals(copy.getOptionalSfixed64(), -0x1234567800000000);
+ assertEquals(copy.getOptionalFloat(), 1.5);
+ assertEquals(copy.getOptionalDouble(), -1.5);
+ assertEquals(copy.getOptionalBool(), true);
+ assertEquals(copy.getOptionalString(), 'hello world');
+ assertEquals(true, bytesCompare(copy.getOptionalBytes(), BYTES));
+ assertEquals(true, bytesCompare(copy.getOptionalBytes_asU8(), BYTES));
+ assertEquals(
+ copy.getOptionalBytes_asB64(), goog.crypt.base64.encodeByteArray(BYTES));
+
+ assertEquals(copy.getOptionalGroup().getA(), 100);
+ assertEquals(copy.getOptionalForeignMessage().getC(), 16);
+ assertEquals(copy.getOptionalForeignEnum(),
+ proto.jspb.test.ForeignEnum.FOREIGN_FOO);
+
+
+ assertEquals(copy.getOneofString(), 'oneof');
+ assertEquals(copy.getOneofFieldCase(),
+ proto.jspb.test.TestAllTypes.OneofFieldCase.ONEOF_STRING);
+
+ assertElementsEquals(copy.getRepeatedInt32List(), [-42]);
+ assertElementsEquals(copy.getRepeatedInt64List(), [-0x7fffffff00000000]);
+ assertElementsEquals(copy.getRepeatedUint32List(), [0x80000000]);
+ assertElementsEquals(copy.getRepeatedUint64List(), [0xf000000000000000]);
+ assertElementsEquals(copy.getRepeatedSint32List(), [-100]);
+ assertElementsEquals(copy.getRepeatedSint64List(), [-0x8000000000000000]);
+ assertElementsEquals(copy.getRepeatedFixed32List(), [1234]);
+ assertElementsEquals(copy.getRepeatedFixed64List(), [0x1234567800000000]);
+ assertElementsEquals(copy.getRepeatedSfixed32List(), [-1234]);
+ assertElementsEquals(copy.getRepeatedSfixed64List(), [-0x1234567800000000]);
+ assertElementsEquals(copy.getRepeatedFloatList(), [1.5]);
+ assertElementsEquals(copy.getRepeatedDoubleList(), [-1.5]);
+ assertElementsEquals(copy.getRepeatedBoolList(), [true]);
+ assertElementsEquals(copy.getRepeatedStringList(), ['hello world']);
+ assertEquals(copy.getRepeatedBytesList().length, 2);
+ assertEquals(true, bytesCompare(copy.getRepeatedBytesList_asU8()[0], BYTES));
+ assertEquals(true, bytesCompare(copy.getRepeatedBytesList()[0], BYTES));
+ assertEquals(true, bytesCompare(copy.getRepeatedBytesList_asU8()[1], BYTES));
+ assertEquals(copy.getRepeatedBytesList_asB64()[0], BYTES_B64);
+ assertEquals(copy.getRepeatedBytesList_asB64()[1], BYTES_B64);
+ assertEquals(copy.getRepeatedGroupList().length, 1);
+ assertEquals(copy.getRepeatedGroupList()[0].getA(), 100);
+ assertEquals(copy.getRepeatedForeignMessageList().length, 1);
+ assertEquals(copy.getRepeatedForeignMessageList()[0].getC(), 1000);
+ assertElementsEquals(copy.getRepeatedForeignEnumList(),
+ [proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+ assertElementsEquals(copy.getPackedRepeatedInt32List(), [-42]);
+ assertElementsEquals(copy.getPackedRepeatedInt64List(),
+ [-0x7fffffff00000000]);
+ assertElementsEquals(copy.getPackedRepeatedUint32List(), [0x80000000]);
+ assertElementsEquals(copy.getPackedRepeatedUint64List(),
+ [0xf000000000000000]);
+ assertElementsEquals(copy.getPackedRepeatedSint32List(), [-100]);
+ assertElementsEquals(copy.getPackedRepeatedSint64List(),
+ [-0x8000000000000000]);
+ assertElementsEquals(copy.getPackedRepeatedFixed32List(), [1234]);
+ assertElementsEquals(copy.getPackedRepeatedFixed64List(),
+ [0x1234567800000000]);
+ assertElementsEquals(copy.getPackedRepeatedSfixed32List(), [-1234]);
+ assertElementsEquals(copy.getPackedRepeatedSfixed64List(),
+ [-0x1234567800000000]);
+ assertElementsEquals(copy.getPackedRepeatedFloatList(), [1.5]);
+ assertElementsEquals(copy.getPackedRepeatedDoubleList(), [-1.5]);
+
+}
+
+
+/**
+ * Helper: verify that all expected extensions are present.
+ * @param {!proto.jspb.test.TestExtendable} msg
+ */
+function checkExtensions(msg) {
+ assertEquals(-42,
+ msg.getExtension(proto.jspb.test.extendOptionalInt32));
+ assertEquals(-0x7fffffff00000000,
+ msg.getExtension(proto.jspb.test.extendOptionalInt64));
+ assertEquals(0x80000000,
+ msg.getExtension(proto.jspb.test.extendOptionalUint32));
+ assertEquals(0xf000000000000000,
+ msg.getExtension(proto.jspb.test.extendOptionalUint64));
+ assertEquals(-100,
+ msg.getExtension(proto.jspb.test.extendOptionalSint32));
+ assertEquals(-0x8000000000000000,
+ msg.getExtension(proto.jspb.test.extendOptionalSint64));
+ assertEquals(1234,
+ msg.getExtension(proto.jspb.test.extendOptionalFixed32));
+ assertEquals(0x1234567800000000,
+ msg.getExtension(proto.jspb.test.extendOptionalFixed64));
+ assertEquals(-1234,
+ msg.getExtension(proto.jspb.test.extendOptionalSfixed32));
+ assertEquals(-0x1234567800000000,
+ msg.getExtension(proto.jspb.test.extendOptionalSfixed64));
+ assertEquals(1.5,
+ msg.getExtension(proto.jspb.test.extendOptionalFloat));
+ assertEquals(-1.5,
+ msg.getExtension(proto.jspb.test.extendOptionalDouble));
+ assertEquals(true,
+ msg.getExtension(proto.jspb.test.extendOptionalBool));
+ assertEquals('hello world',
+ msg.getExtension(proto.jspb.test.extendOptionalString));
+ assertEquals(
+ true, bytesCompare(
+ msg.getExtension(proto.jspb.test.extendOptionalBytes), BYTES));
+ assertEquals(16,
+ msg.getExtension(
+ proto.jspb.test.ExtendsWithMessage.optionalExtension).getFoo());
+
+
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendRepeatedInt32List),
+ [-42]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendRepeatedInt64List),
+ [-0x7fffffff00000000]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendRepeatedUint32List),
+ [0x80000000]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendRepeatedUint64List),
+ [0xf000000000000000]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendRepeatedSint32List),
+ [-100]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendRepeatedSint64List),
+ [-0x8000000000000000]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendRepeatedFixed32List),
+ [1234]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendRepeatedFixed64List),
+ [0x1234567800000000]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendRepeatedSfixed32List),
+ [-1234]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendRepeatedSfixed64List),
+ [-0x1234567800000000]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendRepeatedFloatList),
+ [1.5]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendRepeatedDoubleList),
+ [-1.5]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendRepeatedBoolList),
+ [true]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendRepeatedStringList),
+ ['hello world']);
+ assertEquals(
+ true,
+ bytesCompare(
+ msg.getExtension(proto.jspb.test.extendRepeatedBytesList)[0], BYTES));
+ assertEquals(1000,
+ msg.getExtension(
+ proto.jspb.test.ExtendsWithMessage.repeatedExtensionList)[0]
+ .getFoo());
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendRepeatedForeignEnumList),
+ [proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendPackedRepeatedInt32List),
+ [-42]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendPackedRepeatedInt64List),
+ [-0x7fffffff00000000]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendPackedRepeatedUint32List),
+ [0x80000000]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendPackedRepeatedUint64List),
+ [0xf000000000000000]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendPackedRepeatedSint32List),
+ [-100]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendPackedRepeatedSint64List),
+ [-0x8000000000000000]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendPackedRepeatedFixed32List),
+ [1234]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendPackedRepeatedFixed64List),
+ [0x1234567800000000]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendPackedRepeatedSfixed32List),
+ [-1234]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendPackedRepeatedSfixed64List),
+ [-0x1234567800000000]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendPackedRepeatedFloatList),
+ [1.5]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendPackedRepeatedDoubleList),
+ [-1.5]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendPackedRepeatedBoolList),
+ [true]);
+ assertElementsEquals(
+ msg.getExtension(proto.jspb.test.extendPackedRepeatedForeignEnumList),
+ [proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+}
+
+
+describe('protoBinaryTest', function() {
+ /**
+ * Tests a basic serialization-deserializaton round-trip with all supported
+ * field types (on the TestAllTypes message type).
+ */
+ it('testRoundTrip', function() {
+ var msg = new proto.jspb.test.TestAllTypes();
+ fillAllFields(msg);
+ var encoded = msg.serializeBinary();
+ var decoded = proto.jspb.test.TestAllTypes.deserializeBinary(encoded);
+ checkAllFields(msg, decoded);
+ });
+
+ /**
+ * Test that base64 string and Uint8Array are interchangeable in bytes fields.
+ */
+ it('testBytesFieldsGettersInterop', function() {
+ var msg = new proto.jspb.test.TestAllTypes();
+ // Set from a base64 string and check all the getters work.
+ msg.setOptionalBytes(BYTES_B64);
+ assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+ assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+ assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+ // Test binary serialize round trip doesn't break it.
+ msg = proto.jspb.test.TestAllTypes.deserializeBinary(msg.serializeBinary());
+ assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+ assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+ assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+ msg = new proto.jspb.test.TestAllTypes();
+ // Set from a Uint8Array and check all the getters work.
+ msg.setOptionalBytes(BYTES);
+ assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+ assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+ assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+ });
+
+ /**
+ * Test that bytes setters will receive result of any of the getters.
+ */
+ it('testBytesFieldsSettersInterop', function() {
+ var msg = new proto.jspb.test.TestAllTypes();
+ msg.setOptionalBytes(BYTES);
+ assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+ msg.setOptionalBytes(msg.getOptionalBytes());
+ assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+ msg.setOptionalBytes(msg.getOptionalBytes_asB64());
+ assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+ msg.setOptionalBytes(msg.getOptionalBytes_asU8());
+ assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+ });
+
+ /**
+ * Test that bytes setters will receive result of any of the getters.
+ */
+ it('testRepeatedBytesGetters', function() {
+ var msg = new proto.jspb.test.TestAllTypes();
+
+ function assertGetters() {
+ assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[0]));
+ assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[1]));
+ assertTrue(msg.getRepeatedBytesList_asU8()[0] instanceof Uint8Array);
+ assertTrue(msg.getRepeatedBytesList_asU8()[1] instanceof Uint8Array);
+
+ assertTrue(bytesCompare(msg.getRepeatedBytesList()[0], BYTES));
+ assertTrue(bytesCompare(msg.getRepeatedBytesList()[1], BYTES));
+ assertTrue(bytesCompare(msg.getRepeatedBytesList_asB64()[0], BYTES));
+ assertTrue(bytesCompare(msg.getRepeatedBytesList_asB64()[1], BYTES));
+ assertTrue(bytesCompare(msg.getRepeatedBytesList_asU8()[0], BYTES));
+ assertTrue(bytesCompare(msg.getRepeatedBytesList_asU8()[1], BYTES));
+ }
+
+ msg.setRepeatedBytesList([BYTES, BYTES]);
+ assertGetters();
+
+ msg.setRepeatedBytesList([BYTES_B64, BYTES_B64]);
+ assertGetters();
+
+ msg.setRepeatedBytesList([]);
+ assertEquals(0, msg.getRepeatedBytesList().length);
+ assertEquals(0, msg.getRepeatedBytesList_asB64().length);
+ assertEquals(0, msg.getRepeatedBytesList_asU8().length);
+ });
+
+ /**
+ * Helper: fill all extension values.
+ * @param {proto.jspb.test.TestExtendable} msg
+ */
+ function fillExtensions(msg) {
+ msg.setExtension(
+ proto.jspb.test.extendOptionalInt32, -42);
+ msg.setExtension(
+ proto.jspb.test.extendOptionalInt64, -0x7fffffff00000000);
+ msg.setExtension(
+ proto.jspb.test.extendOptionalUint32, 0x80000000);
+ msg.setExtension(
+ proto.jspb.test.extendOptionalUint64, 0xf000000000000000);
+ msg.setExtension(
+ proto.jspb.test.extendOptionalSint32, -100);
+ msg.setExtension(
+ proto.jspb.test.extendOptionalSint64, -0x8000000000000000);
+ msg.setExtension(
+ proto.jspb.test.extendOptionalFixed32, 1234);
+ msg.setExtension(
+ proto.jspb.test.extendOptionalFixed64, 0x1234567800000000);
+ msg.setExtension(
+ proto.jspb.test.extendOptionalSfixed32, -1234);
+ msg.setExtension(
+ proto.jspb.test.extendOptionalSfixed64, -0x1234567800000000);
+ msg.setExtension(
+ proto.jspb.test.extendOptionalFloat, 1.5);
+ msg.setExtension(
+ proto.jspb.test.extendOptionalDouble, -1.5);
+ msg.setExtension(
+ proto.jspb.test.extendOptionalBool, true);
+ msg.setExtension(
+ proto.jspb.test.extendOptionalString, 'hello world');
+ msg.setExtension(proto.jspb.test.extendOptionalBytes, BYTES);
+ var submsg = new proto.jspb.test.ExtendsWithMessage();
+ submsg.setFoo(16);
+ msg.setExtension(
+ proto.jspb.test.ExtendsWithMessage.optionalExtension, submsg);
+ msg.setExtension(
+ proto.jspb.test.extendOptionalForeignEnum,
+ proto.jspb.test.ForeignEnum.FOREIGN_FOO);
+
+
+ msg.setExtension(
+ proto.jspb.test.extendRepeatedInt32List, [-42]);
+ msg.setExtension(
+ proto.jspb.test.extendRepeatedInt64List, [-0x7fffffff00000000]);
+ msg.setExtension(
+ proto.jspb.test.extendRepeatedUint32List, [0x80000000]);
+ msg.setExtension(
+ proto.jspb.test.extendRepeatedUint64List, [0xf000000000000000]);
+ msg.setExtension(
+ proto.jspb.test.extendRepeatedSint32List, [-100]);
+ msg.setExtension(
+ proto.jspb.test.extendRepeatedSint64List, [-0x8000000000000000]);
+ msg.setExtension(
+ proto.jspb.test.extendRepeatedFixed32List, [1234]);
+ msg.setExtension(
+ proto.jspb.test.extendRepeatedFixed64List, [0x1234567800000000]);
+ msg.setExtension(
+ proto.jspb.test.extendRepeatedSfixed32List, [-1234]);
+ msg.setExtension(
+ proto.jspb.test.extendRepeatedSfixed64List, [-0x1234567800000000]);
+ msg.setExtension(
+ proto.jspb.test.extendRepeatedFloatList, [1.5]);
+ msg.setExtension(
+ proto.jspb.test.extendRepeatedDoubleList, [-1.5]);
+ msg.setExtension(
+ proto.jspb.test.extendRepeatedBoolList, [true]);
+ msg.setExtension(
+ proto.jspb.test.extendRepeatedStringList, ['hello world']);
+ msg.setExtension(proto.jspb.test.extendRepeatedBytesList, [BYTES]);
+ submsg = new proto.jspb.test.ExtendsWithMessage();
+ submsg.setFoo(1000);
+ msg.setExtension(
+ proto.jspb.test.ExtendsWithMessage.repeatedExtensionList, [submsg]);
+ msg.setExtension(proto.jspb.test.extendRepeatedForeignEnumList,
+ [proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+
+ msg.setExtension(
+ proto.jspb.test.extendPackedRepeatedInt32List, [-42]);
+ msg.setExtension(
+ proto.jspb.test.extendPackedRepeatedInt64List, [-0x7fffffff00000000]);
+ msg.setExtension(
+ proto.jspb.test.extendPackedRepeatedUint32List, [0x80000000]);
+ msg.setExtension(
+ proto.jspb.test.extendPackedRepeatedUint64List, [0xf000000000000000]);
+ msg.setExtension(
+ proto.jspb.test.extendPackedRepeatedSint32List, [-100]);
+ msg.setExtension(
+ proto.jspb.test.extendPackedRepeatedSint64List, [-0x8000000000000000]);
+ msg.setExtension(
+ proto.jspb.test.extendPackedRepeatedFixed32List, [1234]);
+ msg.setExtension(
+ proto.jspb.test.extendPackedRepeatedFixed64List, [0x1234567800000000]);
+ msg.setExtension(
+ proto.jspb.test.extendPackedRepeatedSfixed32List, [-1234]);
+ msg.setExtension(
+ proto.jspb.test.extendPackedRepeatedSfixed64List,
+ [-0x1234567800000000]);
+ msg.setExtension(
+ proto.jspb.test.extendPackedRepeatedFloatList, [1.5]);
+ msg.setExtension(
+ proto.jspb.test.extendPackedRepeatedDoubleList, [-1.5]);
+ msg.setExtension(
+ proto.jspb.test.extendPackedRepeatedBoolList, [true]);
+ msg.setExtension(proto.jspb.test.extendPackedRepeatedForeignEnumList,
+ [proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+ }
+
+
+ /**
+ * Tests extension serialization and deserialization.
+ */
+ it('testExtensions', function() {
+ var msg = new proto.jspb.test.TestExtendable();
+ fillExtensions(msg);
+ var encoded = msg.serializeBinary();
+ var decoded = proto.jspb.test.TestExtendable.deserializeBinary(encoded);
+ checkExtensions(decoded);
+ });
+});
diff --git a/js/compatibility_tests/v3.1.0/binary/reader_test.js b/js/compatibility_tests/v3.1.0/binary/reader_test.js
new file mode 100644
index 00000000..95711385
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/binary/reader_test.js
@@ -0,0 +1,922 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/**
+ * @fileoverview Test cases for jspb's binary protocol buffer reader.
+ *
+ * There are two particular magic numbers that need to be pointed out -
+ * 2^64-1025 is the largest number representable as both a double and an
+ * unsigned 64-bit integer, and 2^63-513 is the largest number representable as
+ * both a double and a signed 64-bit integer.
+ *
+ * Test suite is written using Jasmine -- see http://jasmine.github.io/
+ *
+ * @author aappleby@google.com (Austin Appleby)
+ */
+
+goog.require('goog.testing.asserts');
+goog.require('jspb.BinaryConstants');
+goog.require('jspb.BinaryDecoder');
+goog.require('jspb.BinaryReader');
+goog.require('jspb.BinaryWriter');
+
+
+
+describe('binaryReaderTest', function() {
+ /**
+ * Tests the reader instance cache.
+ */
+ it('testInstanceCaches', /** @suppress {visibility} */ function() {
+ var writer = new jspb.BinaryWriter();
+ var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+ writer.writeMessage(1, dummyMessage, goog.nullFunction);
+ writer.writeMessage(2, dummyMessage, goog.nullFunction);
+
+ var buffer = writer.getResultBuffer();
+
+ // Empty the instance caches.
+ jspb.BinaryReader.instanceCache_ = [];
+
+ // Allocating and then freeing three decoders should leave us with three in
+ // the cache.
+
+ var decoder1 = jspb.BinaryDecoder.alloc();
+ var decoder2 = jspb.BinaryDecoder.alloc();
+ var decoder3 = jspb.BinaryDecoder.alloc();
+ decoder1.free();
+ decoder2.free();
+ decoder3.free();
+
+ assertEquals(3, jspb.BinaryDecoder.instanceCache_.length);
+ assertEquals(0, jspb.BinaryReader.instanceCache_.length);
+
+ // Allocating and then freeing a reader should remove one decoder from its
+ // cache, but it should stay stuck to the reader afterwards since we can't
+ // have a reader without a decoder.
+ jspb.BinaryReader.alloc().free();
+
+ assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
+ assertEquals(1, jspb.BinaryReader.instanceCache_.length);
+
+ // Allocating a reader should remove a reader from the cache.
+ var reader = jspb.BinaryReader.alloc(buffer);
+
+ assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
+ assertEquals(0, jspb.BinaryReader.instanceCache_.length);
+
+ // Processing the message reuses the current reader.
+ reader.nextField();
+ assertEquals(1, reader.getFieldNumber());
+ reader.readMessage(dummyMessage, function() {
+ assertEquals(0, jspb.BinaryReader.instanceCache_.length);
+ });
+
+ reader.nextField();
+ assertEquals(2, reader.getFieldNumber());
+ reader.readMessage(dummyMessage, function() {
+ assertEquals(0, jspb.BinaryReader.instanceCache_.length);
+ });
+
+ assertEquals(false, reader.nextField());
+
+ assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
+ assertEquals(0, jspb.BinaryReader.instanceCache_.length);
+
+ // Freeing the reader should put it back into the cache.
+ reader.free();
+
+ assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
+ assertEquals(1, jspb.BinaryReader.instanceCache_.length);
+ });
+
+
+ /**
+ * @param {number} x
+ * @return {number}
+ */
+ function truncate(x) {
+ var temp = new Float32Array(1);
+ temp[0] = x;
+ return temp[0];
+ }
+
+
+ /**
+ * Verifies that misuse of the reader class triggers assertions.
+ */
+ it('testReadErrors', /** @suppress {checkTypes|visibility} */ function() {
+ // Calling readMessage on a non-delimited field should trigger an
+ // assertion.
+ var reader = jspb.BinaryReader.alloc([8, 1]);
+ var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+ reader.nextField();
+ assertThrows(function() {
+ reader.readMessage(dummyMessage, goog.nullFunction);
+ });
+
+ // Reading past the end of the stream should trigger an assertion.
+ reader = jspb.BinaryReader.alloc([9, 1]);
+ reader.nextField();
+ assertThrows(function() {reader.readFixed64()});
+
+ // Reading past the end of a submessage should trigger an assertion.
+ reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]);
+ reader.nextField();
+ reader.readMessage(dummyMessage, function() {
+ reader.nextField();
+ assertThrows(function() {reader.readFixed32()});
+ });
+
+ // Skipping an invalid field should trigger an assertion.
+ reader = jspb.BinaryReader.alloc([12, 1]);
+ reader.nextWireType_ = 1000;
+ assertThrows(function() {reader.skipField()});
+
+ // Reading fields with the wrong wire type should assert.
+ reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]);
+ reader.nextField();
+ assertThrows(function() {reader.readInt32()});
+ assertThrows(function() {reader.readInt32String()});
+ assertThrows(function() {reader.readInt64()});
+ assertThrows(function() {reader.readInt64String()});
+ assertThrows(function() {reader.readUint32()});
+ assertThrows(function() {reader.readUint32String()});
+ assertThrows(function() {reader.readUint64()});
+ assertThrows(function() {reader.readUint64String()});
+ assertThrows(function() {reader.readSint32()});
+ assertThrows(function() {reader.readBool()});
+ assertThrows(function() {reader.readEnum()});
+
+ reader = jspb.BinaryReader.alloc([8, 1]);
+ reader.nextField();
+ assertThrows(function() {reader.readFixed32()});
+ assertThrows(function() {reader.readFixed64()});
+ assertThrows(function() {reader.readSfixed32()});
+ assertThrows(function() {reader.readSfixed64()});
+ assertThrows(function() {reader.readFloat()});
+ assertThrows(function() {reader.readDouble()});
+
+ assertThrows(function() {reader.readString()});
+ assertThrows(function() {reader.readBytes()});
+ });
+
+
+ /**
+ * Tests encoding and decoding of unsigned field types.
+ * @param {Function} readField
+ * @param {Function} writeField
+ * @param {number} epsilon
+ * @param {number} upperLimit
+ * @param {Function} filter
+ * @private
+ * @suppress {missingProperties}
+ */
+ var doTestUnsignedField_ = function(readField,
+ writeField, epsilon, upperLimit, filter) {
+ assertNotNull(readField);
+ assertNotNull(writeField);
+
+ var writer = new jspb.BinaryWriter();
+
+ // Encode zero and limits.
+ writeField.call(writer, 1, filter(0));
+ writeField.call(writer, 2, filter(epsilon));
+ writeField.call(writer, 3, filter(upperLimit));
+
+ // Encode positive values.
+ for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+ writeField.call(writer, 4, filter(cursor));
+ }
+
+ var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+ // Check zero and limits.
+ reader.nextField();
+ assertEquals(1, reader.getFieldNumber());
+ assertEquals(filter(0), readField.call(reader));
+
+ reader.nextField();
+ assertEquals(2, reader.getFieldNumber());
+ assertEquals(filter(epsilon), readField.call(reader));
+
+ reader.nextField();
+ assertEquals(3, reader.getFieldNumber());
+ assertEquals(filter(upperLimit), readField.call(reader));
+
+ // Check positive values.
+ for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+ reader.nextField();
+ if (4 != reader.getFieldNumber()) throw 'fail!';
+ if (filter(cursor) != readField.call(reader)) throw 'fail!';
+ }
+ };
+
+
+ /**
+ * Tests encoding and decoding of signed field types.
+ * @param {Function} readField
+ * @param {Function} writeField
+ * @param {number} epsilon
+ * @param {number} lowerLimit
+ * @param {number} upperLimit
+ * @param {Function} filter
+ * @private
+ * @suppress {missingProperties}
+ */
+ var doTestSignedField_ = function(readField,
+ writeField, epsilon, lowerLimit, upperLimit, filter) {
+ var writer = new jspb.BinaryWriter();
+
+ // Encode zero and limits.
+ writeField.call(writer, 1, filter(lowerLimit));
+ writeField.call(writer, 2, filter(-epsilon));
+ writeField.call(writer, 3, filter(0));
+ writeField.call(writer, 4, filter(epsilon));
+ writeField.call(writer, 5, filter(upperLimit));
+
+ var inputValues = [];
+
+ // Encode negative values.
+ for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) {
+ var val = filter(cursor);
+ writeField.call(writer, 6, val);
+ inputValues.push({
+ fieldNumber: 6,
+ value: val
+ });
+ }
+
+ // Encode positive values.
+ for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+ var val = filter(cursor);
+ writeField.call(writer, 7, val);
+ inputValues.push({
+ fieldNumber: 7,
+ value: val
+ });
+ }
+
+ var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+ // Check zero and limits.
+ reader.nextField();
+ assertEquals(1, reader.getFieldNumber());
+ assertEquals(filter(lowerLimit), readField.call(reader));
+
+ reader.nextField();
+ assertEquals(2, reader.getFieldNumber());
+ assertEquals(filter(-epsilon), readField.call(reader));
+
+ reader.nextField();
+ assertEquals(3, reader.getFieldNumber());
+ assertEquals(filter(0), readField.call(reader));
+
+ reader.nextField();
+ assertEquals(4, reader.getFieldNumber());
+ assertEquals(filter(epsilon), readField.call(reader));
+
+ reader.nextField();
+ assertEquals(5, reader.getFieldNumber());
+ assertEquals(filter(upperLimit), readField.call(reader));
+
+ for (var i = 0; i < inputValues.length; i++) {
+ var expected = inputValues[i];
+ reader.nextField();
+ assertEquals(expected.fieldNumber, reader.getFieldNumber());
+ assertEquals(expected.value, readField.call(reader));
+ }
+ };
+
+
+ /**
+ * Tests fields that use varint encoding.
+ */
+ it('testVarintFields', function() {
+ assertNotUndefined(jspb.BinaryReader.prototype.readUint32);
+ assertNotUndefined(jspb.BinaryWriter.prototype.writeUint32);
+ assertNotUndefined(jspb.BinaryReader.prototype.readUint64);
+ assertNotUndefined(jspb.BinaryWriter.prototype.writeUint64);
+ assertNotUndefined(jspb.BinaryReader.prototype.readBool);
+ assertNotUndefined(jspb.BinaryWriter.prototype.writeBool);
+ doTestUnsignedField_(
+ jspb.BinaryReader.prototype.readUint32,
+ jspb.BinaryWriter.prototype.writeUint32,
+ 1, Math.pow(2, 32) - 1, Math.round);
+
+ doTestUnsignedField_(
+ jspb.BinaryReader.prototype.readUint64,
+ jspb.BinaryWriter.prototype.writeUint64,
+ 1, Math.pow(2, 64) - 1025, Math.round);
+
+ doTestSignedField_(
+ jspb.BinaryReader.prototype.readInt32,
+ jspb.BinaryWriter.prototype.writeInt32,
+ 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+
+ doTestSignedField_(
+ jspb.BinaryReader.prototype.readInt64,
+ jspb.BinaryWriter.prototype.writeInt64,
+ 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+
+ doTestSignedField_(
+ jspb.BinaryReader.prototype.readEnum,
+ jspb.BinaryWriter.prototype.writeEnum,
+ 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+
+ doTestUnsignedField_(
+ jspb.BinaryReader.prototype.readBool,
+ jspb.BinaryWriter.prototype.writeBool,
+ 1, 1, function(x) { return !!x; });
+ });
+
+
+ /**
+ * Tests reading a field from hexadecimal string (format: '08 BE EF').
+ * @param {Function} readField
+ * @param {number} expected
+ * @param {string} hexString
+ */
+ function doTestHexStringVarint_(readField, expected, hexString) {
+ var bytesCount = (hexString.length + 1) / 3;
+ var bytes = new Uint8Array(bytesCount);
+ for (var i = 0; i < bytesCount; i++) {
+ bytes[i] = parseInt(hexString.substring(i * 3, i * 3 + 2), 16);
+ }
+ var reader = jspb.BinaryReader.alloc(bytes);
+ reader.nextField();
+ assertEquals(expected, readField.call(reader));
+ }
+
+
+ /**
+ * Tests non-canonical redundant varint decoding.
+ */
+ it('testRedundantVarintFields', function() {
+ assertNotNull(jspb.BinaryReader.prototype.readUint32);
+ assertNotNull(jspb.BinaryReader.prototype.readUint64);
+ assertNotNull(jspb.BinaryReader.prototype.readSint32);
+ assertNotNull(jspb.BinaryReader.prototype.readSint64);
+
+ // uint32 and sint32 take no more than 5 bytes
+ // 08 - field prefix (type = 0 means varint)
+ doTestHexStringVarint_(
+ jspb.BinaryReader.prototype.readUint32,
+ 12, '08 8C 80 80 80 00');
+
+ // 11 stands for -6 in zigzag encoding
+ doTestHexStringVarint_(
+ jspb.BinaryReader.prototype.readSint32,
+ -6, '08 8B 80 80 80 00');
+
+ // uint64 and sint64 take no more than 10 bytes
+ // 08 - field prefix (type = 0 means varint)
+ doTestHexStringVarint_(
+ jspb.BinaryReader.prototype.readUint64,
+ 12, '08 8C 80 80 80 80 80 80 80 80 00');
+
+ // 11 stands for -6 in zigzag encoding
+ doTestHexStringVarint_(
+ jspb.BinaryReader.prototype.readSint64,
+ -6, '08 8B 80 80 80 80 80 80 80 80 00');
+ });
+
+
+ /**
+ * Tests 64-bit fields that are handled as strings.
+ */
+ it('testStringInt64Fields', function() {
+ var writer = new jspb.BinaryWriter();
+
+ var testSignedData = [
+ '2730538252207801776',
+ '-2688470994844604560',
+ '3398529779486536359',
+ '3568577411627971000',
+ '272477188847484900',
+ '-6649058714086158188',
+ '-7695254765712060806',
+ '-4525541438037104029',
+ '-4993706538836508568',
+ '4990160321893729138'
+ ];
+ var testUnsignedData = [
+ '7822732630241694882',
+ '6753602971916687352',
+ '2399935075244442116',
+ '8724292567325338867',
+ '16948784802625696584',
+ '4136275908516066934',
+ '3575388346793700364',
+ '5167142028379259461',
+ '1557573948689737699',
+ '17100725280812548567'
+ ];
+
+ for (var i = 0; i < testSignedData.length; i++) {
+ writer.writeInt64String(2 * i + 1, testSignedData[i]);
+ writer.writeUint64String(2 * i + 2, testUnsignedData[i]);
+ }
+
+ var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+ for (var i = 0; i < testSignedData.length; i++) {
+ reader.nextField();
+ assertEquals(2 * i + 1, reader.getFieldNumber());
+ assertEquals(testSignedData[i], reader.readInt64String());
+ reader.nextField();
+ assertEquals(2 * i + 2, reader.getFieldNumber());
+ assertEquals(testUnsignedData[i], reader.readUint64String());
+ }
+ });
+
+
+ /**
+ * Tests fields that use zigzag encoding.
+ */
+ it('testZigzagFields', function() {
+ doTestSignedField_(
+ jspb.BinaryReader.prototype.readSint32,
+ jspb.BinaryWriter.prototype.writeSint32,
+ 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+
+ doTestSignedField_(
+ jspb.BinaryReader.prototype.readSint64,
+ jspb.BinaryWriter.prototype.writeSint64,
+ 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+ });
+
+
+ /**
+ * Tests fields that use fixed-length encoding.
+ */
+ it('testFixedFields', function() {
+ doTestUnsignedField_(
+ jspb.BinaryReader.prototype.readFixed32,
+ jspb.BinaryWriter.prototype.writeFixed32,
+ 1, Math.pow(2, 32) - 1, Math.round);
+
+ doTestUnsignedField_(
+ jspb.BinaryReader.prototype.readFixed64,
+ jspb.BinaryWriter.prototype.writeFixed64,
+ 1, Math.pow(2, 64) - 1025, Math.round);
+
+ doTestSignedField_(
+ jspb.BinaryReader.prototype.readSfixed32,
+ jspb.BinaryWriter.prototype.writeSfixed32,
+ 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+
+ doTestSignedField_(
+ jspb.BinaryReader.prototype.readSfixed64,
+ jspb.BinaryWriter.prototype.writeSfixed64,
+ 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+ });
+
+
+ /**
+ * Tests floating point fields.
+ */
+ it('testFloatFields', function() {
+ doTestSignedField_(
+ jspb.BinaryReader.prototype.readFloat,
+ jspb.BinaryWriter.prototype.writeFloat,
+ jspb.BinaryConstants.FLOAT32_MIN,
+ -jspb.BinaryConstants.FLOAT32_MAX,
+ jspb.BinaryConstants.FLOAT32_MAX,
+ truncate);
+
+ doTestSignedField_(
+ jspb.BinaryReader.prototype.readDouble,
+ jspb.BinaryWriter.prototype.writeDouble,
+ jspb.BinaryConstants.FLOAT64_EPS * 10,
+ -jspb.BinaryConstants.FLOAT64_MIN,
+ jspb.BinaryConstants.FLOAT64_MIN,
+ function(x) { return x; });
+ });
+
+
+ /**
+ * Tests length-delimited string fields.
+ */
+ it('testStringFields', function() {
+ var s1 = 'The quick brown fox jumps over the lazy dog.';
+ var s2 = '人人生而自由,在尊嚴和權利上一律平等。';
+
+ var writer = new jspb.BinaryWriter();
+
+ writer.writeString(1, s1);
+ writer.writeString(2, s2);
+
+ var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+ reader.nextField();
+ assertEquals(1, reader.getFieldNumber());
+ assertEquals(s1, reader.readString());
+
+ reader.nextField();
+ assertEquals(2, reader.getFieldNumber());
+ assertEquals(s2, reader.readString());
+ });
+
+
+ /**
+ * Tests length-delimited byte fields.
+ */
+ it('testByteFields', function() {
+ var message = [];
+ var lowerLimit = 1;
+ var upperLimit = 256;
+ var scale = 1.1;
+
+ var writer = new jspb.BinaryWriter();
+
+ for (var cursor = lowerLimit; cursor < upperLimit; cursor *= 1.1) {
+ var len = Math.round(cursor);
+ var bytes = [];
+ for (var i = 0; i < len; i++) bytes.push(i % 256);
+
+ writer.writeBytes(len, bytes);
+ }
+
+ var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+ for (var cursor = lowerLimit; reader.nextField(); cursor *= 1.1) {
+ var len = Math.round(cursor);
+ if (len != reader.getFieldNumber()) throw 'fail!';
+
+ var bytes = reader.readBytes();
+ if (len != bytes.length) throw 'fail!';
+ for (var i = 0; i < bytes.length; i++) {
+ if (i % 256 != bytes[i]) throw 'fail!';
+ }
+ }
+ });
+
+
+ /**
+ * Tests nested messages.
+ */
+ it('testNesting', function() {
+ var writer = new jspb.BinaryWriter();
+ var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+
+ writer.writeInt32(1, 100);
+
+ // Add one message with 3 int fields.
+ writer.writeMessage(2, dummyMessage, function() {
+ writer.writeInt32(3, 300);
+ writer.writeInt32(4, 400);
+ writer.writeInt32(5, 500);
+ });
+
+ // Add one empty message.
+ writer.writeMessage(6, dummyMessage, goog.nullFunction);
+
+ writer.writeInt32(7, 700);
+
+ var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+ // Validate outermost message.
+
+ reader.nextField();
+ assertEquals(1, reader.getFieldNumber());
+ assertEquals(100, reader.readInt32());
+
+ reader.nextField();
+ assertEquals(2, reader.getFieldNumber());
+ reader.readMessage(dummyMessage, function() {
+ // Validate embedded message 1.
+ reader.nextField();
+ assertEquals(3, reader.getFieldNumber());
+ assertEquals(300, reader.readInt32());
+
+ reader.nextField();
+ assertEquals(4, reader.getFieldNumber());
+ assertEquals(400, reader.readInt32());
+
+ reader.nextField();
+ assertEquals(5, reader.getFieldNumber());
+ assertEquals(500, reader.readInt32());
+
+ assertEquals(false, reader.nextField());
+ });
+
+ reader.nextField();
+ assertEquals(6, reader.getFieldNumber());
+ reader.readMessage(dummyMessage, function() {
+ // Validate embedded message 2.
+
+ assertEquals(false, reader.nextField());
+ });
+
+ reader.nextField();
+ assertEquals(7, reader.getFieldNumber());
+ assertEquals(700, reader.readInt32());
+
+ assertEquals(false, reader.nextField());
+ });
+
+ /**
+ * Tests skipping fields of each type by interleaving them with sentinel
+ * values and skipping everything that's not a sentinel.
+ */
+ it('testSkipField', function() {
+ var writer = new jspb.BinaryWriter();
+
+ var sentinel = 123456789;
+
+ // Write varint fields of different sizes.
+ writer.writeInt32(1, sentinel);
+ writer.writeInt32(1, 1);
+ writer.writeInt32(1, 1000);
+ writer.writeInt32(1, 1000000);
+ writer.writeInt32(1, 1000000000);
+
+ // Write fixed 64-bit encoded fields.
+ writer.writeInt32(2, sentinel);
+ writer.writeDouble(2, 1);
+ writer.writeFixed64(2, 1);
+ writer.writeSfixed64(2, 1);
+
+ // Write fixed 32-bit encoded fields.
+ writer.writeInt32(3, sentinel);
+ writer.writeFloat(3, 1);
+ writer.writeFixed32(3, 1);
+ writer.writeSfixed32(3, 1);
+
+ // Write delimited fields.
+ writer.writeInt32(4, sentinel);
+ writer.writeBytes(4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+ writer.writeString(4, 'The quick brown fox jumps over the lazy dog');
+
+ // Write a group with a nested group inside.
+ writer.writeInt32(5, sentinel);
+ var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+ writer.writeGroup(5, dummyMessage, function() {
+ writer.writeInt64(42, 42);
+ writer.writeGroup(6, dummyMessage, function() {
+ writer.writeInt64(84, 42);
+ });
+ });
+
+ // Write final sentinel.
+ writer.writeInt32(6, sentinel);
+
+ var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+ function skip(field, count) {
+ for (var i = 0; i < count; i++) {
+ reader.nextField();
+ if (field != reader.getFieldNumber()) throw 'fail!';
+ reader.skipField();
+ }
+ }
+
+ reader.nextField();
+ assertEquals(1, reader.getFieldNumber());
+ assertEquals(sentinel, reader.readInt32());
+ skip(1, 4);
+
+ reader.nextField();
+ assertEquals(2, reader.getFieldNumber());
+ assertEquals(sentinel, reader.readInt32());
+ skip(2, 3);
+
+ reader.nextField();
+ assertEquals(3, reader.getFieldNumber());
+ assertEquals(sentinel, reader.readInt32());
+ skip(3, 3);
+
+ reader.nextField();
+ assertEquals(4, reader.getFieldNumber());
+ assertEquals(sentinel, reader.readInt32());
+ skip(4, 2);
+
+ reader.nextField();
+ assertEquals(5, reader.getFieldNumber());
+ assertEquals(sentinel, reader.readInt32());
+ skip(5, 1);
+
+ reader.nextField();
+ assertEquals(6, reader.getFieldNumber());
+ assertEquals(sentinel, reader.readInt32());
+ });
+
+
+ /**
+ * Tests packed fields.
+ */
+ it('testPackedFields', function() {
+ var writer = new jspb.BinaryWriter();
+
+ var sentinel = 123456789;
+
+ var unsignedData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+ var signedData = [-1, 2, -3, 4, -5, 6, -7, 8, -9, 10];
+ var floatData = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10];
+ var doubleData = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10];
+ var boolData = [true, false, true, true, false, false, true, false];
+
+ for (var i = 0; i < floatData.length; i++) {
+ floatData[i] = truncate(floatData[i]);
+ }
+
+ writer.writeInt32(1, sentinel);
+
+ writer.writePackedInt32(2, signedData);
+ writer.writePackedInt64(2, signedData);
+ writer.writePackedUint32(2, unsignedData);
+ writer.writePackedUint64(2, unsignedData);
+ writer.writePackedSint32(2, signedData);
+ writer.writePackedSint64(2, signedData);
+ writer.writePackedFixed32(2, unsignedData);
+ writer.writePackedFixed64(2, unsignedData);
+ writer.writePackedSfixed32(2, signedData);
+ writer.writePackedSfixed64(2, signedData);
+ writer.writePackedFloat(2, floatData);
+ writer.writePackedDouble(2, doubleData);
+ writer.writePackedBool(2, boolData);
+ writer.writePackedEnum(2, unsignedData);
+
+ writer.writeInt32(3, sentinel);
+
+ var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+ reader.nextField();
+ assertEquals(sentinel, reader.readInt32());
+
+ reader.nextField();
+ assertElementsEquals(reader.readPackedInt32(), signedData);
+
+ reader.nextField();
+ assertElementsEquals(reader.readPackedInt64(), signedData);
+
+ reader.nextField();
+ assertElementsEquals(reader.readPackedUint32(), unsignedData);
+
+ reader.nextField();
+ assertElementsEquals(reader.readPackedUint64(), unsignedData);
+
+ reader.nextField();
+ assertElementsEquals(reader.readPackedSint32(), signedData);
+
+ reader.nextField();
+ assertElementsEquals(reader.readPackedSint64(), signedData);
+
+ reader.nextField();
+ assertElementsEquals(reader.readPackedFixed32(), unsignedData);
+
+ reader.nextField();
+ assertElementsEquals(reader.readPackedFixed64(), unsignedData);
+
+ reader.nextField();
+ assertElementsEquals(reader.readPackedSfixed32(), signedData);
+
+ reader.nextField();
+ assertElementsEquals(reader.readPackedSfixed64(), signedData);
+
+ reader.nextField();
+ assertElementsEquals(reader.readPackedFloat(), floatData);
+
+ reader.nextField();
+ assertElementsEquals(reader.readPackedDouble(), doubleData);
+
+ reader.nextField();
+ assertElementsEquals(reader.readPackedBool(), boolData);
+
+ reader.nextField();
+ assertElementsEquals(reader.readPackedEnum(), unsignedData);
+
+ reader.nextField();
+ assertEquals(sentinel, reader.readInt32());
+ });
+
+
+ /**
+ * Byte blobs inside nested messages should always have their byte offset set
+ * relative to the start of the outermost blob, not the start of their parent
+ * blob.
+ */
+ it('testNestedBlobs', function() {
+ // Create a proto consisting of two nested messages, with the inner one
+ // containing a blob of bytes.
+
+ var fieldTag = (1 << 3) | jspb.BinaryConstants.WireType.DELIMITED;
+ var blob = [1, 2, 3, 4, 5];
+ var writer = new jspb.BinaryWriter();
+ var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+
+ writer.writeMessage(1, dummyMessage, function() {
+ writer.writeMessage(1, dummyMessage, function() {
+ writer.writeBytes(1, blob);
+ });
+ });
+
+ // Peel off the outer two message layers. Each layer should have two bytes
+ // of overhead, one for the field tag and one for the length of the inner
+ // blob.
+
+ var decoder1 = new jspb.BinaryDecoder(writer.getResultBuffer());
+ assertEquals(fieldTag, decoder1.readUnsignedVarint32());
+ assertEquals(blob.length + 4, decoder1.readUnsignedVarint32());
+
+ var decoder2 = new jspb.BinaryDecoder(decoder1.readBytes(blob.length + 4));
+ assertEquals(fieldTag, decoder2.readUnsignedVarint32());
+ assertEquals(blob.length + 2, decoder2.readUnsignedVarint32());
+
+ assertEquals(fieldTag, decoder2.readUnsignedVarint32());
+ assertEquals(blob.length, decoder2.readUnsignedVarint32());
+ var bytes = decoder2.readBytes(blob.length);
+
+ assertElementsEquals(bytes, blob);
+ });
+
+
+ /**
+ * Tests read callbacks.
+ */
+ it('testReadCallbacks', function() {
+ var writer = new jspb.BinaryWriter();
+ var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+
+ // Add an int, a submessage, and another int.
+ writer.writeInt32(1, 100);
+
+ writer.writeMessage(2, dummyMessage, function() {
+ writer.writeInt32(3, 300);
+ writer.writeInt32(4, 400);
+ writer.writeInt32(5, 500);
+ });
+
+ writer.writeInt32(7, 700);
+
+ // Create the reader and register a custom read callback.
+ var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+ /**
+ * @param {!jspb.BinaryReader} reader
+ * @return {*}
+ */
+ function readCallback(reader) {
+ reader.nextField();
+ assertEquals(3, reader.getFieldNumber());
+ assertEquals(300, reader.readInt32());
+
+ reader.nextField();
+ assertEquals(4, reader.getFieldNumber());
+ assertEquals(400, reader.readInt32());
+
+ reader.nextField();
+ assertEquals(5, reader.getFieldNumber());
+ assertEquals(500, reader.readInt32());
+
+ assertEquals(false, reader.nextField());
+ };
+
+ reader.registerReadCallback('readCallback', readCallback);
+
+ // Read the container message.
+ reader.nextField();
+ assertEquals(1, reader.getFieldNumber());
+ assertEquals(100, reader.readInt32());
+
+ reader.nextField();
+ assertEquals(2, reader.getFieldNumber());
+ reader.readMessage(dummyMessage, function() {
+ // Decode the embedded message using the registered callback.
+ reader.runReadCallback('readCallback');
+ });
+
+ reader.nextField();
+ assertEquals(7, reader.getFieldNumber());
+ assertEquals(700, reader.readInt32());
+
+ assertEquals(false, reader.nextField());
+ });
+});
diff --git a/js/compatibility_tests/v3.1.0/binary/utils_test.js b/js/compatibility_tests/v3.1.0/binary/utils_test.js
new file mode 100644
index 00000000..d27e5ea2
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/binary/utils_test.js
@@ -0,0 +1,668 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/**
+ * @fileoverview Test cases for jspb's helper functions.
+ *
+ * Test suite is written using Jasmine -- see http://jasmine.github.io/
+ *
+ * @author aappleby@google.com (Austin Appleby)
+ */
+
+goog.require('goog.crypt.base64');
+goog.require('goog.testing.asserts');
+goog.require('jspb.BinaryConstants');
+goog.require('jspb.BinaryWriter');
+goog.require('jspb.utils');
+
+
+/**
+ * @param {number} x
+ * @return {number}
+ */
+function truncate(x) {
+ var temp = new Float32Array(1);
+ temp[0] = x;
+ return temp[0];
+}
+
+
+/**
+ * Converts an 64-bit integer in split representation to a 64-bit hash string
+ * (8 bits encoded per character).
+ * @param {number} bitsLow The low 32 bits of the split 64-bit integer.
+ * @param {number} bitsHigh The high 32 bits of the split 64-bit integer.
+ * @return {string} The encoded hash string, 8 bits per character.
+ */
+function toHashString(bitsLow, bitsHigh) {
+ return String.fromCharCode((bitsLow >>> 0) & 0xFF,
+ (bitsLow >>> 8) & 0xFF,
+ (bitsLow >>> 16) & 0xFF,
+ (bitsLow >>> 24) & 0xFF,
+ (bitsHigh >>> 0) & 0xFF,
+ (bitsHigh >>> 8) & 0xFF,
+ (bitsHigh >>> 16) & 0xFF,
+ (bitsHigh >>> 24) & 0xFF);
+}
+
+
+describe('binaryUtilsTest', function() {
+ /**
+ * Tests lossless binary-to-decimal conversion.
+ */
+ it('testDecimalConversion', function() {
+ // Check some magic numbers.
+ var result =
+ jspb.utils.joinUnsignedDecimalString(0x89e80001, 0x8ac72304);
+ assertEquals('10000000000000000001', result);
+
+ result = jspb.utils.joinUnsignedDecimalString(0xacd05f15, 0x1b69b4b);
+ assertEquals('123456789123456789', result);
+
+ result = jspb.utils.joinUnsignedDecimalString(0xeb1f0ad2, 0xab54a98c);
+ assertEquals('12345678901234567890', result);
+
+ result = jspb.utils.joinUnsignedDecimalString(0xe3b70cb1, 0x891087b8);
+ assertEquals('9876543210987654321', result);
+
+ // Check limits.
+ result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00000000);
+ assertEquals('0', result);
+
+ result = jspb.utils.joinUnsignedDecimalString(0xFFFFFFFF, 0xFFFFFFFF);
+ assertEquals('18446744073709551615', result);
+
+ // Check each bit of the low dword.
+ for (var i = 0; i < 32; i++) {
+ var low = (1 << i) >>> 0;
+ result = jspb.utils.joinUnsignedDecimalString(low, 0);
+ assertEquals('' + Math.pow(2, i), result);
+ }
+
+ // Check the first 20 bits of the high dword.
+ for (var i = 0; i < 20; i++) {
+ var high = (1 << i) >>> 0;
+ result = jspb.utils.joinUnsignedDecimalString(0, high);
+ assertEquals('' + Math.pow(2, 32 + i), result);
+ }
+
+ // V8's internal double-to-string conversion is inaccurate for values above
+ // 2^52, even if they're representable integers - check the rest of the bits
+ // manually against the correct string representations of 2^N.
+
+ result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00100000);
+ assertEquals('4503599627370496', result);
+
+ result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00200000);
+ assertEquals('9007199254740992', result);
+
+ result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00400000);
+ assertEquals('18014398509481984', result);
+
+ result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00800000);
+ assertEquals('36028797018963968', result);
+
+ result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x01000000);
+ assertEquals('72057594037927936', result);
+
+ result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x02000000);
+ assertEquals('144115188075855872', result);
+
+ result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x04000000);
+ assertEquals('288230376151711744', result);
+
+ result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x08000000);
+ assertEquals('576460752303423488', result);
+
+ result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x10000000);
+ assertEquals('1152921504606846976', result);
+
+ result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x20000000);
+ assertEquals('2305843009213693952', result);
+
+ result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x40000000);
+ assertEquals('4611686018427387904', result);
+
+ result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x80000000);
+ assertEquals('9223372036854775808', result);
+ });
+
+
+ /**
+ * Going from hash strings to decimal strings should also be lossless.
+ */
+ it('testHashToDecimalConversion', function() {
+ var result;
+ var convert = jspb.utils.hash64ToDecimalString;
+
+ result = convert(toHashString(0x00000000, 0x00000000), false);
+ assertEquals('0', result);
+
+ result = convert(toHashString(0x00000000, 0x00000000), true);
+ assertEquals('0', result);
+
+ result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF), false);
+ assertEquals('18446744073709551615', result);
+
+ result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF), true);
+ assertEquals('-1', result);
+
+ result = convert(toHashString(0x00000000, 0x80000000), false);
+ assertEquals('9223372036854775808', result);
+
+ result = convert(toHashString(0x00000000, 0x80000000), true);
+ assertEquals('-9223372036854775808', result);
+
+ result = convert(toHashString(0xacd05f15, 0x01b69b4b), false);
+ assertEquals('123456789123456789', result);
+
+ result = convert(toHashString(~0xacd05f15 + 1, ~0x01b69b4b), true);
+ assertEquals('-123456789123456789', result);
+
+ // And converting arrays of hashes should work the same way.
+ result = jspb.utils.hash64ArrayToDecimalStrings([
+ toHashString(0xFFFFFFFF, 0xFFFFFFFF),
+ toHashString(0x00000000, 0x80000000),
+ toHashString(0xacd05f15, 0x01b69b4b)], false);
+ assertEquals(3, result.length);
+ assertEquals('18446744073709551615', result[0]);
+ assertEquals('9223372036854775808', result[1]);
+ assertEquals('123456789123456789', result[2]);
+ });
+
+ /*
+ * Going from decimal strings to hash strings should be lossless.
+ */
+ it('testDecimalToHashConversion', function() {
+ var result;
+ var convert = jspb.utils.decimalStringToHash64;
+
+ result = convert('0');
+ assertEquals(String.fromCharCode.apply(null,
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), result);
+
+ result = convert('-1');
+ assertEquals(String.fromCharCode.apply(null,
+ [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
+
+ result = convert('18446744073709551615');
+ assertEquals(String.fromCharCode.apply(null,
+ [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
+
+ result = convert('9223372036854775808');
+ assertEquals(String.fromCharCode.apply(null,
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result);
+
+ result = convert('-9223372036854775808');
+ assertEquals(String.fromCharCode.apply(null,
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result);
+
+ result = convert('123456789123456789');
+ assertEquals(String.fromCharCode.apply(null,
+ [0x15, 0x5F, 0xD0, 0xAC, 0x4B, 0x9B, 0xB6, 0x01]), result);
+
+ result = convert('-123456789123456789');
+ assertEquals(String.fromCharCode.apply(null,
+ [0xEB, 0xA0, 0x2F, 0x53, 0xB4, 0x64, 0x49, 0xFE]), result);
+ });
+
+ /**
+ * Going from hash strings to hex strings should be lossless.
+ */
+ it('testHashToHexConversion', function() {
+ var result;
+ var convert = jspb.utils.hash64ToHexString;
+
+ result = convert(toHashString(0x00000000, 0x00000000));
+ assertEquals('0x0000000000000000', result);
+
+ result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF));
+ assertEquals('0xffffffffffffffff', result);
+
+ result = convert(toHashString(0x12345678, 0x9ABCDEF0));
+ assertEquals('0x9abcdef012345678', result);
+ });
+
+
+ /**
+ * Going from hex strings to hash strings should be lossless.
+ */
+ it('testHexToHashConversion', function() {
+ var result;
+ var convert = jspb.utils.hexStringToHash64;
+
+ result = convert('0x0000000000000000');
+ assertEquals(String.fromCharCode.apply(null,
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), result);
+
+ result = convert('0xffffffffffffffff');
+ assertEquals(String.fromCharCode.apply(null,
+ [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
+
+ // Hex string is big-endian, hash string is little-endian.
+ result = convert('0x123456789ABCDEF0');
+ assertEquals(String.fromCharCode.apply(null,
+ [0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]), result);
+
+ // Capitalization should not matter.
+ result = convert('0x0000abcdefABCDEF');
+ assertEquals(String.fromCharCode.apply(null,
+ [0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB, 0x00, 0x00]), result);
+ });
+
+
+ /**
+ * Going from numbers to hash strings should be lossless for up to 53 bits of
+ * precision.
+ */
+ it('testNumberToHashConversion', function() {
+ var result;
+ var convert = jspb.utils.numberToHash64;
+
+ result = convert(0x0000000000000);
+ assertEquals('0x0000000000000000', jspb.utils.hash64ToHexString(result));
+
+ result = convert(0xFFFFFFFFFFFFF);
+ assertEquals('0x000fffffffffffff', jspb.utils.hash64ToHexString(result));
+
+ result = convert(0x123456789ABCD);
+ assertEquals('0x000123456789abcd', jspb.utils.hash64ToHexString(result));
+
+ result = convert(0xDCBA987654321);
+ assertEquals('0x000dcba987654321', jspb.utils.hash64ToHexString(result));
+
+ // 53 bits of precision should not be truncated.
+ result = convert(0x10000000000001);
+ assertEquals('0x0010000000000001', jspb.utils.hash64ToHexString(result));
+
+ // 54 bits of precision should be truncated.
+ result = convert(0x20000000000001);
+ assertNotEquals(
+ '0x0020000000000001', jspb.utils.hash64ToHexString(result));
+ });
+
+
+ /**
+ * Sanity check the behavior of Javascript's strings when doing funny things
+ * with unicode characters.
+ */
+ it('sanityCheckUnicodeStrings', function() {
+ var strings = new Array(65536);
+
+ // All possible unsigned 16-bit values should be storable in a string, they
+ // shouldn't do weird things with the length of the string, and they should
+ // come back out of the string unchanged.
+ for (var i = 0; i < 65536; i++) {
+ strings[i] = 'a' + String.fromCharCode(i) + 'a';
+ if (3 != strings[i].length) throw 'fail!';
+ if (i != strings[i].charCodeAt(1)) throw 'fail!';
+ }
+
+ // Each unicode character should compare equal to itself and not equal to a
+ // different unicode character.
+ for (var i = 0; i < 65536; i++) {
+ if (strings[i] != strings[i]) throw 'fail!';
+ if (strings[i] == strings[(i + 1) % 65536]) throw 'fail!';
+ }
+ });
+
+
+ /**
+ * Tests conversion from 32-bit floating point numbers to split64 numbers.
+ */
+ it('testFloat32ToSplit64', function() {
+ var f32_eps = jspb.BinaryConstants.FLOAT32_EPS;
+ var f32_min = jspb.BinaryConstants.FLOAT32_MIN;
+ var f32_max = jspb.BinaryConstants.FLOAT32_MAX;
+
+ // NaN.
+ jspb.utils.splitFloat32(NaN);
+ if (!isNaN(jspb.utils.joinFloat32(jspb.utils.split64Low,
+ jspb.utils.split64High))) {
+ throw 'fail!';
+ }
+
+ /**
+ * @param {number} x
+ * @param {number=} opt_bits
+ */
+ function test(x, opt_bits) {
+ jspb.utils.splitFloat32(x);
+ if (goog.isDef(opt_bits)) {
+ if (opt_bits != jspb.utils.split64Low) throw 'fail!';
+ }
+ if (truncate(x) != jspb.utils.joinFloat32(jspb.utils.split64Low,
+ jspb.utils.split64High)) {
+ throw 'fail!';
+ }
+ }
+
+ // Positive and negative infinity.
+ test(Infinity, 0x7f800000);
+ test(-Infinity, 0xff800000);
+
+ // Positive and negative zero.
+ test(0, 0x00000000);
+ test(-0, 0x80000000);
+
+ // Positive and negative epsilon.
+ test(f32_eps, 0x00000001);
+ test(-f32_eps, 0x80000001);
+
+ // Positive and negative min.
+ test(f32_min, 0x00800000);
+ test(-f32_min, 0x80800000);
+
+ // Positive and negative max.
+ test(f32_max, 0x7F7FFFFF);
+ test(-f32_max, 0xFF7FFFFF);
+
+ // Various positive values.
+ var cursor = f32_eps * 10;
+ while (cursor != Infinity) {
+ test(cursor);
+ cursor *= 1.1;
+ }
+
+ // Various negative values.
+ cursor = -f32_eps * 10;
+ while (cursor != -Infinity) {
+ test(cursor);
+ cursor *= 1.1;
+ }
+ });
+
+
+ /**
+ * Tests conversion from 64-bit floating point numbers to split64 numbers.
+ */
+ it('testFloat64ToSplit64', function() {
+ var f64_eps = jspb.BinaryConstants.FLOAT64_EPS;
+ var f64_min = jspb.BinaryConstants.FLOAT64_MIN;
+ var f64_max = jspb.BinaryConstants.FLOAT64_MAX;
+
+ // NaN.
+ jspb.utils.splitFloat64(NaN);
+ if (!isNaN(jspb.utils.joinFloat64(jspb.utils.split64Low,
+ jspb.utils.split64High))) {
+ throw 'fail!';
+ }
+
+ /**
+ * @param {number} x
+ * @param {number=} opt_highBits
+ * @param {number=} opt_lowBits
+ */
+ function test(x, opt_highBits, opt_lowBits) {
+ jspb.utils.splitFloat64(x);
+ if (goog.isDef(opt_highBits)) {
+ if (opt_highBits != jspb.utils.split64High) throw 'fail!';
+ }
+ if (goog.isDef(opt_lowBits)) {
+ if (opt_lowBits != jspb.utils.split64Low) throw 'fail!';
+ }
+ if (x != jspb.utils.joinFloat64(jspb.utils.split64Low,
+ jspb.utils.split64High)) {
+ throw 'fail!';
+ }
+ }
+
+ // Positive and negative infinity.
+ test(Infinity, 0x7ff00000, 0x00000000);
+ test(-Infinity, 0xfff00000, 0x00000000);
+
+ // Positive and negative zero.
+ test(0, 0x00000000, 0x00000000);
+ test(-0, 0x80000000, 0x00000000);
+
+ // Positive and negative epsilon.
+ test(f64_eps, 0x00000000, 0x00000001);
+ test(-f64_eps, 0x80000000, 0x00000001);
+
+ // Positive and negative min.
+ test(f64_min, 0x00100000, 0x00000000);
+ test(-f64_min, 0x80100000, 0x00000000);
+
+ // Positive and negative max.
+ test(f64_max, 0x7FEFFFFF, 0xFFFFFFFF);
+ test(-f64_max, 0xFFEFFFFF, 0xFFFFFFFF);
+
+ // Various positive values.
+ var cursor = f64_eps * 10;
+ while (cursor != Infinity) {
+ test(cursor);
+ cursor *= 1.1;
+ }
+
+ // Various negative values.
+ cursor = -f64_eps * 10;
+ while (cursor != -Infinity) {
+ test(cursor);
+ cursor *= 1.1;
+ }
+ });
+
+
+ /**
+ * Tests counting packed varints.
+ */
+ it('testCountVarints', function() {
+ var values = [];
+ for (var i = 1; i < 1000000000; i *= 1.1) {
+ values.push(Math.floor(i));
+ }
+
+ var writer = new jspb.BinaryWriter();
+ writer.writePackedUint64(1, values);
+
+ var buffer = new Uint8Array(writer.getResultBuffer());
+
+ // We should have two more varints than we started with - one for the field
+ // tag, one for the packed length.
+ assertEquals(values.length + 2,
+ jspb.utils.countVarints(buffer, 0, buffer.length));
+ });
+
+
+ /**
+ * Tests counting matching varint fields.
+ */
+ it('testCountVarintFields', function() {
+ var writer = new jspb.BinaryWriter();
+
+ var count = 0;
+ for (var i = 1; i < 1000000000; i *= 1.1) {
+ writer.writeUint64(1, Math.floor(i));
+ count++;
+ }
+ writer.writeString(2, 'terminator');
+
+ var buffer = new Uint8Array(writer.getResultBuffer());
+ assertEquals(count,
+ jspb.utils.countVarintFields(buffer, 0, buffer.length, 1));
+
+ writer = new jspb.BinaryWriter();
+
+ count = 0;
+ for (var i = 1; i < 1000000000; i *= 1.1) {
+ writer.writeUint64(123456789, Math.floor(i));
+ count++;
+ }
+ writer.writeString(2, 'terminator');
+
+ buffer = new Uint8Array(writer.getResultBuffer());
+ assertEquals(count,
+ jspb.utils.countVarintFields(buffer, 0, buffer.length, 123456789));
+ });
+
+
+ /**
+ * Tests counting matching fixed32 fields.
+ */
+ it('testCountFixed32Fields', function() {
+ var writer = new jspb.BinaryWriter();
+
+ var count = 0;
+ for (var i = 1; i < 1000000000; i *= 1.1) {
+ writer.writeFixed32(1, Math.floor(i));
+ count++;
+ }
+ writer.writeString(2, 'terminator');
+
+ var buffer = new Uint8Array(writer.getResultBuffer());
+ assertEquals(count,
+ jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 1));
+
+ writer = new jspb.BinaryWriter();
+
+ count = 0;
+ for (var i = 1; i < 1000000000; i *= 1.1) {
+ writer.writeFixed32(123456789, Math.floor(i));
+ count++;
+ }
+ writer.writeString(2, 'terminator');
+
+ buffer = new Uint8Array(writer.getResultBuffer());
+ assertEquals(count,
+ jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 123456789));
+ });
+
+
+ /**
+ * Tests counting matching fixed64 fields.
+ */
+ it('testCountFixed64Fields', function() {
+ var writer = new jspb.BinaryWriter();
+
+ var count = 0;
+ for (var i = 1; i < 1000000000; i *= 1.1) {
+ writer.writeDouble(1, i);
+ count++;
+ }
+ writer.writeString(2, 'terminator');
+
+ var buffer = new Uint8Array(writer.getResultBuffer());
+ assertEquals(count,
+ jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 1));
+
+ writer = new jspb.BinaryWriter();
+
+ count = 0;
+ for (var i = 1; i < 1000000000; i *= 1.1) {
+ writer.writeDouble(123456789, i);
+ count++;
+ }
+ writer.writeString(2, 'terminator');
+
+ buffer = new Uint8Array(writer.getResultBuffer());
+ assertEquals(count,
+ jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 123456789));
+ });
+
+
+ /**
+ * Tests counting matching delimited fields.
+ */
+ it('testCountDelimitedFields', function() {
+ var writer = new jspb.BinaryWriter();
+
+ var count = 0;
+ for (var i = 1; i < 1000; i *= 1.1) {
+ writer.writeBytes(1, [Math.floor(i)]);
+ count++;
+ }
+ writer.writeString(2, 'terminator');
+
+ var buffer = new Uint8Array(writer.getResultBuffer());
+ assertEquals(count,
+ jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 1));
+
+ writer = new jspb.BinaryWriter();
+
+ count = 0;
+ for (var i = 1; i < 1000; i *= 1.1) {
+ writer.writeBytes(123456789, [Math.floor(i)]);
+ count++;
+ }
+ writer.writeString(2, 'terminator');
+
+ buffer = new Uint8Array(writer.getResultBuffer());
+ assertEquals(count,
+ jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 123456789));
+ });
+
+
+ /**
+ * Tests byte format for debug strings.
+ */
+ it('testDebugBytesToTextFormat', function() {
+ assertEquals('""', jspb.utils.debugBytesToTextFormat(null));
+ assertEquals('"\\x00\\x10\\xff"',
+ jspb.utils.debugBytesToTextFormat([0, 16, 255]));
+ });
+
+
+ /**
+ * Tests converting byte blob sources into byte blobs.
+ */
+ it('testByteSourceToUint8Array', function() {
+ var convert = jspb.utils.byteSourceToUint8Array;
+
+ var sourceData = [];
+ for (var i = 0; i < 256; i++) {
+ sourceData.push(i);
+ }
+
+ var sourceBytes = new Uint8Array(sourceData);
+ var sourceBuffer = sourceBytes.buffer;
+ var sourceBase64 = goog.crypt.base64.encodeByteArray(sourceData);
+ var sourceString = String.fromCharCode.apply(null, sourceData);
+
+ function check(result) {
+ assertEquals(Uint8Array, result.constructor);
+ assertEquals(sourceData.length, result.length);
+ for (var i = 0; i < result.length; i++) {
+ assertEquals(sourceData[i], result[i]);
+ }
+ }
+
+ // Converting Uint8Arrays into Uint8Arrays should be a no-op.
+ assertEquals(sourceBytes, convert(sourceBytes));
+
+ // Converting Array.<numbers> into Uint8Arrays should work.
+ check(convert(sourceData));
+
+ // Converting ArrayBuffers into Uint8Arrays should work.
+ check(convert(sourceBuffer));
+
+ // Converting base64-encoded strings into Uint8Arrays should work.
+ check(convert(sourceBase64));
+ });
+});
diff --git a/js/compatibility_tests/v3.1.0/binary/writer_test.js b/js/compatibility_tests/v3.1.0/binary/writer_test.js
new file mode 100644
index 00000000..d5dadb41
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/binary/writer_test.js
@@ -0,0 +1,122 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/**
+ * @fileoverview Test cases for jspb's binary protocol buffer writer. In
+ * practice BinaryWriter is used to drive the Decoder and Reader test cases,
+ * so only writer-specific tests are here.
+ *
+ * Test suite is written using Jasmine -- see http://jasmine.github.io/
+ *
+ * @author aappleby@google.com (Austin Appleby)
+ */
+
+goog.require('goog.crypt');
+goog.require('goog.testing.asserts');
+goog.require('jspb.BinaryWriter');
+
+
+/**
+ * @param {function()} func This function should throw an error when run.
+ */
+function assertFails(func) {
+ var e = assertThrows(func);
+ //assertNotNull(e.toString().match(/Error/));
+}
+
+
+describe('binaryWriterTest', function() {
+ /**
+ * Verifies that misuse of the writer class triggers assertions.
+ */
+ it('testWriteErrors', function() {
+ // Submessages with invalid field indices should assert.
+ var writer = new jspb.BinaryWriter();
+ var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+
+ assertFails(function() {
+ writer.writeMessage(-1, dummyMessage, goog.nullFunction);
+ });
+
+ // Writing invalid field indices should assert.
+ writer = new jspb.BinaryWriter();
+ assertFails(function() {writer.writeUint64(-1, 1);});
+
+ // Writing out-of-range field values should assert.
+ writer = new jspb.BinaryWriter();
+
+ assertFails(function() {writer.writeInt32(1, -Infinity);});
+ assertFails(function() {writer.writeInt32(1, Infinity);});
+
+ assertFails(function() {writer.writeInt64(1, -Infinity);});
+ assertFails(function() {writer.writeInt64(1, Infinity);});
+
+ assertFails(function() {writer.writeUint32(1, -1);});
+ assertFails(function() {writer.writeUint32(1, Infinity);});
+
+ assertFails(function() {writer.writeUint64(1, -1);});
+ assertFails(function() {writer.writeUint64(1, Infinity);});
+
+ assertFails(function() {writer.writeSint32(1, -Infinity);});
+ assertFails(function() {writer.writeSint32(1, Infinity);});
+
+ assertFails(function() {writer.writeSint64(1, -Infinity);});
+ assertFails(function() {writer.writeSint64(1, Infinity);});
+
+ assertFails(function() {writer.writeFixed32(1, -1);});
+ assertFails(function() {writer.writeFixed32(1, Infinity);});
+
+ assertFails(function() {writer.writeFixed64(1, -1);});
+ assertFails(function() {writer.writeFixed64(1, Infinity);});
+
+ assertFails(function() {writer.writeSfixed32(1, -Infinity);});
+ assertFails(function() {writer.writeSfixed32(1, Infinity);});
+
+ assertFails(function() {writer.writeSfixed64(1, -Infinity);});
+ assertFails(function() {writer.writeSfixed64(1, Infinity);});
+ });
+
+
+ /**
+ * Basic test of retrieving the result as a Uint8Array buffer
+ */
+ it('testGetResultBuffer', function() {
+ var expected = '0864120b48656c6c6f20776f726c641a0301020320c801';
+
+ var writer = new jspb.BinaryWriter();
+ writer.writeUint32(1, 100);
+ writer.writeString(2, 'Hello world');
+ writer.writeBytes(3, new Uint8Array([1, 2, 3]));
+ writer.writeUint32(4, 200);
+
+ var buffer = writer.getResultBuffer();
+ assertEquals(expected, goog.crypt.byteArrayToHex(buffer));
+ });
+});
diff --git a/js/compatibility_tests/v3.1.0/commonjs/test6/test6.proto b/js/compatibility_tests/v3.1.0/commonjs/test6/test6.proto
new file mode 100644
index 00000000..a060925f
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/commonjs/test6/test6.proto
@@ -0,0 +1,40 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.test.importing;
+
+message ImportedMessage {
+ string string_value = 1;
+}
diff --git a/js/compatibility_tests/v3.1.0/commonjs/test7/test7.proto b/js/compatibility_tests/v3.1.0/commonjs/test7/test7.proto
new file mode 100644
index 00000000..f5574a3d
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/commonjs/test7/test7.proto
@@ -0,0 +1,42 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.test.framing;
+
+import "test6/test6.proto";
+
+message FramingMessage {
+ jspb.test.importing.ImportedMessage imported_message = 1;
+}
diff --git a/js/compatibility_tests/v3.1.0/data.proto b/js/compatibility_tests/v3.1.0/data.proto
new file mode 100644
index 00000000..74a8a994
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/data.proto
@@ -0,0 +1,51 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: mwr@google.com (Mark Rawling)
+
+syntax = "proto2";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.test;
+
+// legacy data, must be nested
+message data {
+ message NestedData {
+ required string str = 1;
+ }
+}
+
+// new data, does not require nesting
+message UnnestedData {
+ required string str = 1;
+}
+
diff --git a/js/compatibility_tests/v3.1.0/debug_test.js b/js/compatibility_tests/v3.1.0/debug_test.js
new file mode 100644
index 00000000..702cc76e
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/debug_test.js
@@ -0,0 +1,105 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+goog.setTestOnly();
+
+goog.require('goog.testing.asserts');
+
+// CommonJS-LoadFromFile: google-protobuf
+goog.require('jspb.debug');
+
+// CommonJS-LoadFromFile: test_pb
+goog.require('proto.jspb.test.HasExtensions');
+goog.require('proto.jspb.test.IsExtension');
+goog.require('proto.jspb.test.Simple1');
+
+
+
+describe('debugTest', function() {
+ it('testSimple1', function() {
+ if (COMPILED) {
+ return;
+ }
+ var message = new proto.jspb.test.Simple1();
+ message.setAString('foo');
+ assertObjectEquals({
+ $name: 'proto.jspb.test.Simple1',
+ 'aString': 'foo',
+ 'aRepeatedStringList': []
+ }, jspb.debug.dump(message));
+
+ message.setABoolean(true);
+ message.setARepeatedStringList(['1', '2']);
+
+ assertObjectEquals({
+ $name: 'proto.jspb.test.Simple1',
+ 'aString': 'foo',
+ 'aRepeatedStringList': ['1', '2'],
+ 'aBoolean': true
+ }, jspb.debug.dump(message));
+
+ message.clearAString();
+
+ assertObjectEquals({
+ $name: 'proto.jspb.test.Simple1',
+ 'aRepeatedStringList': ['1', '2'],
+ 'aBoolean': true
+ }, jspb.debug.dump(message));
+ });
+
+
+ it('testExtensions', function() {
+ if (COMPILED) {
+ return;
+ }
+ var extension = new proto.jspb.test.IsExtension();
+ extension.setExt1('ext1field');
+ var extendable = new proto.jspb.test.HasExtensions();
+ extendable.setStr1('v1');
+ extendable.setStr2('v2');
+ extendable.setStr3('v3');
+ extendable.setExtension(proto.jspb.test.IsExtension.extField, extension);
+
+ assertObjectEquals({
+ '$name': 'proto.jspb.test.HasExtensions',
+ 'str1': 'v1',
+ 'str2': 'v2',
+ 'str3': 'v3',
+ '$extensions': {
+ 'extField': {
+ '$name': 'proto.jspb.test.IsExtension',
+ 'ext1': 'ext1field'
+ },
+ 'repeatedSimpleList': []
+ }
+ }, jspb.debug.dump(extendable));
+ });
+
+});
diff --git a/js/compatibility_tests/v3.1.0/maps_test.js b/js/compatibility_tests/v3.1.0/maps_test.js
new file mode 100644
index 00000000..0d442f4f
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/maps_test.js
@@ -0,0 +1,301 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+goog.require('goog.testing.asserts');
+goog.require('goog.userAgent');
+
+// CommonJS-LoadFromFile: testbinary_pb proto.jspb.test
+goog.require('proto.jspb.test.MapValueEnum');
+goog.require('proto.jspb.test.MapValueMessage');
+goog.require('proto.jspb.test.TestMapFields');
+
+// CommonJS-LoadFromFile: test_pb proto.jspb.test
+goog.require('proto.jspb.test.MapValueMessageNoBinary');
+goog.require('proto.jspb.test.TestMapFieldsNoBinary');
+
+/**
+ * Helper: check that the given map has exactly this set of (sorted) entries.
+ * @param {!jspb.Map} map
+ * @param {!Array<!Array<?>>} entries
+ */
+function checkMapEquals(map, entries) {
+ var arr = map.toArray();
+ assertEquals(arr.length, entries.length);
+ for (var i = 0; i < arr.length; i++) {
+ assertElementsEquals(arr[i], entries[i]);
+ }
+}
+
+/**
+ * Converts an ES6 iterator to an array.
+ * @template T
+ * @param {!Iterator<T>} iter an iterator
+ * @return {!Array<T>}
+ */
+function toArray(iter) {
+ var arr = [];
+ while (true) {
+ var val = iter.next();
+ if (val.done) {
+ break;
+ }
+ arr.push(val.value);
+ }
+ return arr;
+}
+
+
+/**
+ * Helper: generate test methods for this TestMapFields class.
+ * @param {?} msgInfo
+ * @param {?} submessageCtor
+ * @param {!string} suffix
+ */
+function makeTests(msgInfo, submessageCtor, suffix) {
+ /**
+ * Helper: fill all maps on a TestMapFields.
+ * @param {?} msg
+ */
+ var fillMapFields = function(msg) {
+ msg.getMapStringStringMap().set('asdf', 'jkl;').set('key 2', 'hello world');
+ msg.getMapStringInt32Map().set('a', 1).set('b', -2);
+ msg.getMapStringInt64Map().set('c', 0x100000000).set('d', 0x200000000);
+ msg.getMapStringBoolMap().set('e', true).set('f', false);
+ msg.getMapStringDoubleMap().set('g', 3.14159).set('h', 2.71828);
+ msg.getMapStringEnumMap()
+ .set('i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR)
+ .set('j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ);
+ msg.getMapStringMsgMap()
+ .set('k', new submessageCtor())
+ .set('l', new submessageCtor());
+ msg.getMapStringMsgMap().get('k').setFoo(42);
+ msg.getMapStringMsgMap().get('l').setFoo(84);
+ msg.getMapInt32StringMap().set(-1, 'a').set(42, 'b');
+ msg.getMapInt64StringMap().set(0x123456789abc, 'c').set(0xcba987654321, 'd');
+ msg.getMapBoolStringMap().set(false, 'e').set(true, 'f');
+ };
+
+ /**
+ * Helper: check all maps on a TestMapFields.
+ * @param {?} msg
+ */
+ var checkMapFields = function(msg) {
+ checkMapEquals(msg.getMapStringStringMap(), [
+ ['asdf', 'jkl;'],
+ ['key 2', 'hello world']
+ ]);
+ checkMapEquals(msg.getMapStringInt32Map(), [
+ ['a', 1],
+ ['b', -2]
+ ]);
+ checkMapEquals(msg.getMapStringInt64Map(), [
+ ['c', 0x100000000],
+ ['d', 0x200000000]
+ ]);
+ checkMapEquals(msg.getMapStringBoolMap(), [
+ ['e', true],
+ ['f', false]
+ ]);
+ checkMapEquals(msg.getMapStringDoubleMap(), [
+ ['g', 3.14159],
+ ['h', 2.71828]
+ ]);
+ checkMapEquals(msg.getMapStringEnumMap(), [
+ ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR],
+ ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ]
+ ]);
+ checkMapEquals(msg.getMapInt32StringMap(), [
+ [-1, 'a'],
+ [42, 'b']
+ ]);
+ checkMapEquals(msg.getMapInt64StringMap(), [
+ [0x123456789abc, 'c'],
+ [0xcba987654321, 'd']
+ ]);
+ checkMapEquals(msg.getMapBoolStringMap(), [
+ [false, 'e'],
+ [true, 'f']
+ ]);
+
+ assertEquals(msg.getMapStringMsgMap().getLength(), 2);
+ assertEquals(msg.getMapStringMsgMap().get('k').getFoo(), 42);
+ assertEquals(msg.getMapStringMsgMap().get('l').getFoo(), 84);
+
+ var entries = toArray(msg.getMapStringMsgMap().entries());
+ assertEquals(entries.length, 2);
+ entries.forEach(function(entry) {
+ var key = entry[0];
+ var val = entry[1];
+ assert(val === msg.getMapStringMsgMap().get(key));
+ });
+
+ msg.getMapStringMsgMap().forEach(function(val, key) {
+ assert(val === msg.getMapStringMsgMap().get(key));
+ });
+ };
+
+ it('testMapStringStringField' + suffix, function() {
+ var msg = new msgInfo.constructor();
+ assertEquals(msg.getMapStringStringMap().getLength(), 0);
+ assertEquals(msg.getMapStringInt32Map().getLength(), 0);
+ assertEquals(msg.getMapStringInt64Map().getLength(), 0);
+ assertEquals(msg.getMapStringBoolMap().getLength(), 0);
+ assertEquals(msg.getMapStringDoubleMap().getLength(), 0);
+ assertEquals(msg.getMapStringEnumMap().getLength(), 0);
+ assertEquals(msg.getMapStringMsgMap().getLength(), 0);
+
+ // Re-create to clear out any internally-cached wrappers, etc.
+ msg = new msgInfo.constructor();
+ var m = msg.getMapStringStringMap();
+ assertEquals(m.has('asdf'), false);
+ assertEquals(m.get('asdf'), undefined);
+ m.set('asdf', 'hello world');
+ assertEquals(m.has('asdf'), true);
+ assertEquals(m.get('asdf'), 'hello world');
+ m.set('jkl;', 'key 2');
+ assertEquals(m.has('jkl;'), true);
+ assertEquals(m.get('jkl;'), 'key 2');
+ assertEquals(m.getLength(), 2);
+ var it = m.entries();
+ assertElementsEquals(it.next().value, ['asdf', 'hello world']);
+ assertElementsEquals(it.next().value, ['jkl;', 'key 2']);
+ assertEquals(it.next().done, true);
+ checkMapEquals(m, [
+ ['asdf', 'hello world'],
+ ['jkl;', 'key 2']
+ ]);
+ m.del('jkl;');
+ assertEquals(m.has('jkl;'), false);
+ assertEquals(m.get('jkl;'), undefined);
+ assertEquals(m.getLength(), 1);
+ it = m.keys();
+ assertEquals(it.next().value, 'asdf');
+ assertEquals(it.next().done, true);
+ it = m.values();
+ assertEquals(it.next().value, 'hello world');
+ assertEquals(it.next().done, true);
+
+ var count = 0;
+ m.forEach(function(value, key, map) {
+ assertEquals(map, m);
+ assertEquals(key, 'asdf');
+ assertEquals(value, 'hello world');
+ count++;
+ });
+ assertEquals(count, 1);
+
+ m.clear();
+ assertEquals(m.getLength(), 0);
+ });
+
+
+ /**
+ * Tests operations on maps with all key and value types.
+ */
+ it('testAllMapTypes' + suffix, function() {
+ var msg = new msgInfo.constructor();
+ fillMapFields(msg);
+ checkMapFields(msg);
+ });
+
+
+ if (msgInfo.deserializeBinary) {
+ /**
+ * Tests serialization and deserialization in binary format.
+ */
+ it('testBinaryFormat' + suffix, function() {
+ if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(10)) {
+ // IE8/9 currently doesn't support binary format because they lack
+ // TypedArray.
+ return;
+ }
+
+ // Check that the format is correct.
+ var msg = new msgInfo.constructor();
+ msg.getMapStringStringMap().set('A', 'a');
+ var serialized = msg.serializeBinary();
+ var expectedSerialized = [
+ 0x0a, 0x6, // field 1 (map_string_string), delimited, length 6
+ 0x0a, 0x1, // field 1 in submessage (key), delimited, length 1
+ 0x41, // ASCII 'A'
+ 0x12, 0x1, // field 2 in submessage (value), delimited, length 1
+ 0x61 // ASCII 'a'
+ ];
+ assertEquals(serialized.length, expectedSerialized.length);
+ for (var i = 0; i < serialized.length; i++) {
+ assertEquals(serialized[i], expectedSerialized[i]);
+ }
+
+ // Check that all map fields successfully round-trip.
+ msg = new msgInfo.constructor();
+ fillMapFields(msg);
+ serialized = msg.serializeBinary();
+ var decoded = msgInfo.deserializeBinary(serialized);
+ checkMapFields(decoded);
+ });
+ }
+
+ /**
+ * Exercises the lazy map<->underlying array sync.
+ */
+ it('testLazyMapSync' + suffix, function() {
+ // Start with a JSPB array containing a few map entries.
+ var entries = [
+ ['a', 'entry 1'],
+ ['c', 'entry 2'],
+ ['b', 'entry 3']
+ ];
+ var msg = new msgInfo.constructor([entries]);
+ assertEquals(entries.length, 3);
+ assertEquals(entries[0][0], 'a');
+ assertEquals(entries[1][0], 'c');
+ assertEquals(entries[2][0], 'b');
+ msg.getMapStringStringMap().del('a');
+ assertEquals(entries.length, 3); // not yet sync'd
+ msg.toArray(); // force a sync
+ assertEquals(entries.length, 2);
+ assertEquals(entries[0][0], 'b'); // now in sorted order
+ assertEquals(entries[1][0], 'c');
+
+ var a = msg.toArray();
+ assertEquals(a[0], entries); // retains original reference
+ });
+}
+
+describe('mapsTest', function() {
+ makeTests({
+ constructor: proto.jspb.test.TestMapFields,
+ deserializeBinary: proto.jspb.test.TestMapFields.deserializeBinary
+ }, proto.jspb.test.MapValueMessage, "_Binary");
+ makeTests({
+ constructor: proto.jspb.test.TestMapFieldsNoBinary,
+ deserializeBinary: null
+ }, proto.jspb.test.MapValueMessageNoBinary, "_NoBinary");
+});
diff --git a/js/compatibility_tests/v3.1.0/message_test.js b/js/compatibility_tests/v3.1.0/message_test.js
new file mode 100644
index 00000000..b46e50d3
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/message_test.js
@@ -0,0 +1,1037 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test suite is written using Jasmine -- see http://jasmine.github.io/
+
+goog.setTestOnly();
+
+goog.require('goog.json');
+goog.require('goog.testing.asserts');
+goog.require('goog.userAgent');
+
+// CommonJS-LoadFromFile: google-protobuf jspb
+goog.require('jspb.Message');
+
+// CommonJS-LoadFromFile: test5_pb proto.jspb.exttest.beta
+goog.require('proto.jspb.exttest.beta.floatingStrField');
+
+// CommonJS-LoadFromFile: test3_pb proto.jspb.exttest
+goog.require('proto.jspb.exttest.floatingMsgField');
+
+// CommonJS-LoadFromFile: test4_pb proto.jspb.exttest
+goog.require('proto.jspb.exttest.floatingMsgFieldTwo');
+
+// CommonJS-LoadFromFile: test_pb proto.jspb.test
+goog.require('proto.jspb.test.CloneExtension');
+goog.require('proto.jspb.test.Complex');
+goog.require('proto.jspb.test.DefaultValues');
+goog.require('proto.jspb.test.Empty');
+goog.require('proto.jspb.test.EnumContainer');
+goog.require('proto.jspb.test.floatingMsgField');
+goog.require('proto.jspb.test.FloatingPointFields');
+goog.require('proto.jspb.test.floatingStrField');
+goog.require('proto.jspb.test.HasExtensions');
+goog.require('proto.jspb.test.IndirectExtension');
+goog.require('proto.jspb.test.IsExtension');
+goog.require('proto.jspb.test.OptionalFields');
+goog.require('proto.jspb.test.OuterEnum');
+goog.require('proto.jspb.test.OuterMessage.Complex');
+goog.require('proto.jspb.test.Simple1');
+goog.require('proto.jspb.test.Simple2');
+goog.require('proto.jspb.test.SpecialCases');
+goog.require('proto.jspb.test.TestClone');
+goog.require('proto.jspb.test.TestEndsWithBytes');
+goog.require('proto.jspb.test.TestGroup');
+goog.require('proto.jspb.test.TestGroup1');
+goog.require('proto.jspb.test.TestMessageWithOneof');
+goog.require('proto.jspb.test.TestReservedNames');
+goog.require('proto.jspb.test.TestReservedNamesExtension');
+
+// CommonJS-LoadFromFile: test2_pb proto.jspb.test
+goog.require('proto.jspb.test.ExtensionMessage');
+goog.require('proto.jspb.test.TestExtensionsMessage');
+
+
+
+
+describe('Message test suite', function() {
+ it('testEmptyProto', function() {
+ var empty1 = new proto.jspb.test.Empty([]);
+ var empty2 = new proto.jspb.test.Empty([]);
+ assertObjectEquals({}, empty1.toObject());
+ assertObjectEquals('Message should not be corrupted:', empty2, empty1);
+ });
+
+ it('testTopLevelEnum', function() {
+ var response = new proto.jspb.test.EnumContainer([]);
+ response.setOuterEnum(proto.jspb.test.OuterEnum.FOO);
+ assertEquals(proto.jspb.test.OuterEnum.FOO, response.getOuterEnum());
+ });
+
+ it('testByteStrings', function() {
+ var data = new proto.jspb.test.DefaultValues([]);
+ data.setBytesField('some_bytes');
+ assertEquals('some_bytes', data.getBytesField());
+ });
+
+ it('testComplexConversion', function() {
+ var data1 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1];
+ var data2 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1];
+ var foo = new proto.jspb.test.Complex(data1);
+ var bar = new proto.jspb.test.Complex(data2);
+ var result = foo.toObject();
+ assertObjectEquals({
+ aString: 'a',
+ anOutOfOrderBool: 1,
+ aNestedMessage: {
+ anInt: 11
+ },
+ aRepeatedMessageList: [{anInt: 22}, {anInt: 33}],
+ aRepeatedStringList: ['s1', 's2']
+ }, result);
+
+ // Now test with the jspb instances included.
+ result = foo.toObject(true /* opt_includeInstance */);
+ assertObjectEquals({
+ aString: 'a',
+ anOutOfOrderBool: 1,
+ aNestedMessage: {
+ anInt: 11,
+ $jspbMessageInstance: foo.getANestedMessage()
+ },
+ aRepeatedMessageList: [
+ {anInt: 22, $jspbMessageInstance: foo.getARepeatedMessageList()[0]},
+ {anInt: 33, $jspbMessageInstance: foo.getARepeatedMessageList()[1]}
+ ],
+ aRepeatedStringList: ['s1', 's2'],
+ $jspbMessageInstance: foo
+ }, result);
+
+ });
+
+ it('testMissingFields', function() {
+ var foo = new proto.jspb.test.Complex([
+ undefined, undefined, undefined, [],
+ undefined, undefined, undefined, undefined]);
+ var bar = new proto.jspb.test.Complex([
+ undefined, undefined, undefined, [],
+ undefined, undefined, undefined, undefined]);
+ var result = foo.toObject();
+ assertObjectEquals({
+ aString: undefined,
+ anOutOfOrderBool: undefined,
+ aNestedMessage: {
+ anInt: undefined
+ },
+ // Note: JsPb converts undefined repeated fields to empty arrays.
+ aRepeatedMessageList: [],
+ aRepeatedStringList: []
+ }, result);
+
+ });
+
+ it('testNestedComplexMessage', function() {
+ // Instantiate the message and set a unique field, just to ensure that we
+ // are not getting jspb.test.Complex instead.
+ var msg = new proto.jspb.test.OuterMessage.Complex();
+ msg.setInnerComplexField(5);
+ });
+
+ it('testSpecialCases', function() {
+ // Note: Some property names are reserved in JavaScript.
+ // These names are converted to the Js property named pb_<reserved_name>.
+ var special =
+ new proto.jspb.test.SpecialCases(['normal', 'default', 'function',
+ 'var']);
+ var result = special.toObject();
+ assertObjectEquals({
+ normal: 'normal',
+ pb_default: 'default',
+ pb_function: 'function',
+ pb_var: 'var'
+ }, result);
+ });
+
+ it('testDefaultValues', function() {
+ var defaultString = "default<>\'\"abc";
+ var response = new proto.jspb.test.DefaultValues();
+
+ // Test toObject
+ var expectedObject = {
+ stringField: defaultString,
+ boolField: true,
+ intField: 11,
+ enumField: 13,
+ emptyField: '',
+ bytesField: 'bW9v'
+ };
+ assertObjectEquals(expectedObject, response.toObject());
+
+
+ // Test getters
+ response = new proto.jspb.test.DefaultValues();
+ assertEquals(defaultString, response.getStringField());
+ assertEquals(true, response.getBoolField());
+ assertEquals(11, response.getIntField());
+ assertEquals(13, response.getEnumField());
+ assertEquals('', response.getEmptyField());
+ assertEquals('bW9v', response.getBytesField());
+
+ function makeDefault(values) {
+ return new proto.jspb.test.DefaultValues(values);
+ }
+
+ // Test with undefined values,
+ // Use push to workaround IE treating undefined array elements as holes.
+ response = makeDefault([undefined, undefined, undefined, undefined]);
+ assertEquals(defaultString, response.getStringField());
+ assertEquals(true, response.getBoolField());
+ assertEquals(11, response.getIntField());
+ assertEquals(13, response.getEnumField());
+ assertFalse(response.hasStringField());
+ assertFalse(response.hasBoolField());
+ assertFalse(response.hasIntField());
+ assertFalse(response.hasEnumField());
+
+ // Test with null values, as would be returned by a JSON serializer.
+ response = makeDefault([null, null, null, null]);
+ assertEquals(defaultString, response.getStringField());
+ assertEquals(true, response.getBoolField());
+ assertEquals(11, response.getIntField());
+ assertEquals(13, response.getEnumField());
+ assertFalse(response.hasStringField());
+ assertFalse(response.hasBoolField());
+ assertFalse(response.hasIntField());
+ assertFalse(response.hasEnumField());
+
+ // Test with false-like values.
+ response = makeDefault(['', false, 0, 0]);
+ assertEquals('', response.getStringField());
+ assertEquals(false, response.getBoolField());
+ assertEquals(true, response.getIntField() == 0);
+ assertEquals(true, response.getEnumField() == 0);
+ assertTrue(response.hasStringField());
+ assertTrue(response.hasBoolField());
+ assertTrue(response.hasIntField());
+ assertTrue(response.hasEnumField());
+
+ // Test that clearing the values reverts them to the default state.
+ response = makeDefault(['blah', false, 111, 77]);
+ response.clearStringField(); response.clearBoolField();
+ response.clearIntField(); response.clearEnumField();
+ assertEquals(defaultString, response.getStringField());
+ assertEquals(true, response.getBoolField());
+ assertEquals(11, response.getIntField());
+ assertEquals(13, response.getEnumField());
+ assertFalse(response.hasStringField());
+ assertFalse(response.hasBoolField());
+ assertFalse(response.hasIntField());
+ assertFalse(response.hasEnumField());
+
+ // Test that setFoo(null) clears the values.
+ response = makeDefault(['blah', false, 111, 77]);
+ response.setStringField(null); response.setBoolField(null);
+ response.setIntField(undefined); response.setEnumField(undefined);
+ assertEquals(defaultString, response.getStringField());
+ assertEquals(true, response.getBoolField());
+ assertEquals(11, response.getIntField());
+ assertEquals(13, response.getEnumField());
+ assertFalse(response.hasStringField());
+ assertFalse(response.hasBoolField());
+ assertFalse(response.hasIntField());
+ assertFalse(response.hasEnumField());
+ });
+
+ it('testClearFields', function() {
+ var data = ['str', true, [11], [[22], [33]], ['s1', 's2']];
+ var foo = new proto.jspb.test.OptionalFields(data);
+ foo.clearAString();
+ foo.clearABool();
+ foo.clearANestedMessage();
+ foo.clearARepeatedMessageList();
+ foo.clearARepeatedStringList();
+ assertEquals('', foo.getAString());
+ assertEquals(false, foo.getABool());
+ assertUndefined(foo.getANestedMessage());
+ assertFalse(foo.hasAString());
+ assertFalse(foo.hasABool());
+ assertObjectEquals([], foo.getARepeatedMessageList());
+ assertObjectEquals([], foo.getARepeatedStringList());
+ // NOTE: We want the missing fields in 'expected' to be undefined,
+ // but we actually get a sparse array instead. We could use something
+ // like [1,undefined,2] to avoid this, except that this is still
+ // sparse on IE. No comment...
+ var expected = [,,, [], []];
+ expected[0] = expected[1] = expected[2] = undefined;
+ assertObjectEquals(expected, foo.toArray());
+ });
+
+ it('testDifferenceRawObject', /** @suppress {visibility} */ function() {
+ var p1 = new proto.jspb.test.HasExtensions(['hi', 'diff', {}]);
+ var p2 = new proto.jspb.test.HasExtensions(['hi', 'what',
+ {1000: 'unique'}]);
+ var diff = /** @type {proto.jspb.test.HasExtensions} */
+ (jspb.Message.difference(p1, p2));
+ assertEquals('', diff.getStr1());
+ assertEquals('what', diff.getStr2());
+ assertEquals('', diff.getStr3());
+ assertEquals('unique', diff.extensionObject_[1000]);
+ });
+
+ it('testEqualsSimple', function() {
+ var s1 = new proto.jspb.test.Simple1(['hi']);
+ assertTrue(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi'])));
+ assertFalse(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['bye'])));
+ var s1b = new proto.jspb.test.Simple1(['hi', ['hello']]);
+ assertTrue(jspb.Message.equals(s1b,
+ new proto.jspb.test.Simple1(['hi', ['hello']])));
+ assertTrue(jspb.Message.equals(s1b,
+ new proto.jspb.test.Simple1(['hi', ['hello', undefined,
+ undefined, undefined]])));
+ assertFalse(jspb.Message.equals(s1b,
+ new proto.jspb.test.Simple1(['no', ['hello']])));
+ // Test with messages of different types
+ var s2 = new proto.jspb.test.Simple2(['hi']);
+ assertFalse(jspb.Message.equals(s1, s2));
+ });
+
+ it('testEquals_softComparison', function() {
+ var s1 = new proto.jspb.test.Simple1(['hi', [], null]);
+ assertTrue(jspb.Message.equals(s1,
+ new proto.jspb.test.Simple1(['hi', []])));
+
+ var s1b = new proto.jspb.test.Simple1(['hi', [], true]);
+ assertTrue(jspb.Message.equals(s1b,
+ new proto.jspb.test.Simple1(['hi', [], 1])));
+ });
+
+ it('testEqualsComplex', function() {
+ var data1 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1];
+ var data2 = ['a',,, [, 11], [[, 22], [, 34]],, ['s1', 's2'],, 1];
+ var data3 = ['a',,, [, 11], [[, 22]],, ['s1', 's2'],, 1];
+ var data4 = ['hi'];
+ var c1a = new proto.jspb.test.Complex(data1);
+ var c1b = new proto.jspb.test.Complex(data1);
+ var c2 = new proto.jspb.test.Complex(data2);
+ var c3 = new proto.jspb.test.Complex(data3);
+ var s1 = new proto.jspb.test.Simple1(data4);
+
+ assertTrue(jspb.Message.equals(c1a, c1b));
+ assertFalse(jspb.Message.equals(c1a, c2));
+ assertFalse(jspb.Message.equals(c2, c3));
+ assertFalse(jspb.Message.equals(c1a, s1));
+ });
+
+ it('testEqualsExtensionsConstructed', function() {
+ assertTrue(jspb.Message.equals(
+ new proto.jspb.test.HasExtensions([]),
+ new proto.jspb.test.HasExtensions([{}])
+ ));
+ assertTrue(jspb.Message.equals(
+ new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
+ new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}])
+ ));
+ assertFalse(jspb.Message.equals(
+ new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
+ new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'b'}]}])
+ ));
+ assertTrue(jspb.Message.equals(
+ new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]),
+ new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}])
+ ));
+ assertTrue(jspb.Message.equals(
+ new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]),
+ new proto.jspb.test.HasExtensions([,,, {100: [{200: 'a'}]}])
+ ));
+ assertTrue(jspb.Message.equals(
+ new proto.jspb.test.HasExtensions([,,, {100: [{200: 'a'}]}]),
+ new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}])
+ ));
+ assertTrue(jspb.Message.equals(
+ new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
+ new proto.jspb.test.HasExtensions(['hi',,, {100: [{200: 'a'}]}])
+ ));
+ assertTrue(jspb.Message.equals(
+ new proto.jspb.test.HasExtensions(['hi',,, {100: [{200: 'a'}]}]),
+ new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}])
+ ));
+ });
+
+ it('testEqualsExtensionsUnconstructed', function() {
+ assertTrue(jspb.Message.compareFields([], [{}]));
+ assertTrue(jspb.Message.compareFields([,,, {}], []));
+ assertTrue(jspb.Message.compareFields([,,, {}], [,, {}]));
+ assertTrue(jspb.Message.compareFields(
+ ['hi', {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}]));
+ assertFalse(jspb.Message.compareFields(
+ ['hi', {100: [{200: 'a'}]}], ['hi', {100: [{200: 'b'}]}]));
+ assertTrue(jspb.Message.compareFields(
+ [{100: [{200: 'a'}]}], [{100: [{200: 'a'}]}]));
+ assertTrue(jspb.Message.compareFields(
+ [{100: [{200: 'a'}]}], [,,, {100: [{200: 'a'}]}]));
+ assertTrue(jspb.Message.compareFields(
+ [,,, {100: [{200: 'a'}]}], [{100: [{200: 'a'}]}]));
+ assertTrue(jspb.Message.compareFields(
+ ['hi', {100: [{200: 'a'}]}], ['hi',,, {100: [{200: 'a'}]}]));
+ assertTrue(jspb.Message.compareFields(
+ ['hi',,, {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}]));
+ });
+
+ it('testToMap', function() {
+ var p1 = new proto.jspb.test.Simple1(['k', ['v']]);
+ var p2 = new proto.jspb.test.Simple1(['k1', ['v1', 'v2']]);
+ var soymap = jspb.Message.toMap([p1, p2],
+ proto.jspb.test.Simple1.prototype.getAString,
+ proto.jspb.test.Simple1.prototype.toObject);
+ assertEquals('k', soymap['k'].aString);
+ assertArrayEquals(['v'], soymap['k'].aRepeatedStringList);
+ var protomap = jspb.Message.toMap([p1, p2],
+ proto.jspb.test.Simple1.prototype.getAString);
+ assertEquals('k', protomap['k'].getAString());
+ assertArrayEquals(['v'], protomap['k'].getARepeatedStringList());
+ });
+
+ it('testClone', function() {
+ var supportsUint8Array =
+ !goog.userAgent.IE || goog.userAgent.isVersionOrHigher('10');
+ var original = new proto.jspb.test.TestClone();
+ original.setStr('v1');
+ var simple1 = new proto.jspb.test.Simple1(['x1', ['y1', 'z1']]);
+ var simple2 = new proto.jspb.test.Simple1(['x2', ['y2', 'z2']]);
+ var simple3 = new proto.jspb.test.Simple1(['x3', ['y3', 'z3']]);
+ original.setSimple1(simple1);
+ original.setSimple2List([simple2, simple3]);
+ var bytes1 = supportsUint8Array ? new Uint8Array([1, 2, 3]) : '123';
+ original.setBytesField(bytes1);
+ var extension = new proto.jspb.test.CloneExtension();
+ extension.setExt('e1');
+ original.setExtension(proto.jspb.test.IsExtension.extField, extension);
+ var clone = original.clone();
+ assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],,
+ [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1,, { 100: [, 'e1'] }],
+ clone.toArray());
+ clone.setStr('v2');
+ var simple4 = new proto.jspb.test.Simple1(['a1', ['b1', 'c1']]);
+ var simple5 = new proto.jspb.test.Simple1(['a2', ['b2', 'c2']]);
+ var simple6 = new proto.jspb.test.Simple1(['a3', ['b3', 'c3']]);
+ clone.setSimple1(simple4);
+ clone.setSimple2List([simple5, simple6]);
+ if (supportsUint8Array) {
+ clone.getBytesField()[0] = 4;
+ assertObjectEquals(bytes1, original.getBytesField());
+ }
+ var bytes2 = supportsUint8Array ? new Uint8Array([4, 5, 6]) : '456';
+ clone.setBytesField(bytes2);
+ var newExtension = new proto.jspb.test.CloneExtension();
+ newExtension.setExt('e2');
+ clone.setExtension(proto.jspb.test.CloneExtension.extField, newExtension);
+ assertArrayEquals(['v2',, ['a1', ['b1', 'c1']],,
+ [['a2', ['b2', 'c2']], ['a3', ['b3', 'c3']]], bytes2,, { 100: [, 'e2'] }],
+ clone.toArray());
+ assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],,
+ [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1,, { 100: [, 'e1'] }],
+ original.toArray());
+ });
+
+ it('testCopyInto', function() {
+ var supportsUint8Array =
+ !goog.userAgent.IE || goog.userAgent.isVersionOrHigher('10');
+ var original = new proto.jspb.test.TestClone();
+ original.setStr('v1');
+ var dest = new proto.jspb.test.TestClone();
+ dest.setStr('override');
+ var simple1 = new proto.jspb.test.Simple1(['x1', ['y1', 'z1']]);
+ var simple2 = new proto.jspb.test.Simple1(['x2', ['y2', 'z2']]);
+ var simple3 = new proto.jspb.test.Simple1(['x3', ['y3', 'z3']]);
+ var destSimple1 = new proto.jspb.test.Simple1(['ox1', ['oy1', 'oz1']]);
+ var destSimple2 = new proto.jspb.test.Simple1(['ox2', ['oy2', 'oz2']]);
+ var destSimple3 = new proto.jspb.test.Simple1(['ox3', ['oy3', 'oz3']]);
+ original.setSimple1(simple1);
+ original.setSimple2List([simple2, simple3]);
+ dest.setSimple1(destSimple1);
+ dest.setSimple2List([destSimple2, destSimple3]);
+ var bytes1 = supportsUint8Array ? new Uint8Array([1, 2, 3]) : '123';
+ var bytes2 = supportsUint8Array ? new Uint8Array([4, 5, 6]) : '456';
+ original.setBytesField(bytes1);
+ dest.setBytesField(bytes2);
+ var extension = new proto.jspb.test.CloneExtension();
+ extension.setExt('e1');
+ original.setExtension(proto.jspb.test.CloneExtension.extField, extension);
+
+ jspb.Message.copyInto(original, dest);
+ assertArrayEquals(original.toArray(), dest.toArray());
+ assertEquals('x1', dest.getSimple1().getAString());
+ assertEquals('e1',
+ dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt());
+ dest.getSimple1().setAString('new value');
+ assertNotEquals(dest.getSimple1().getAString(),
+ original.getSimple1().getAString());
+ if (supportsUint8Array) {
+ dest.getBytesField()[0] = 7;
+ assertObjectEquals(bytes1, original.getBytesField());
+ assertObjectEquals(new Uint8Array([7, 2, 3]), dest.getBytesField());
+ } else {
+ dest.setBytesField('789');
+ assertObjectEquals(bytes1, original.getBytesField());
+ assertObjectEquals('789', dest.getBytesField());
+ }
+ dest.getExtension(proto.jspb.test.CloneExtension.extField).
+ setExt('new value');
+ assertNotEquals(
+ dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt(),
+ original.getExtension(
+ proto.jspb.test.CloneExtension.extField).getExt());
+ });
+
+ it('testCopyInto_notSameType', function() {
+ var a = new proto.jspb.test.TestClone();
+ var b = new proto.jspb.test.Simple1(['str', ['s1', 's2']]);
+
+ var e = assertThrows(function() {
+ jspb.Message.copyInto(a, b);
+ });
+ assertContains('should have the same type', e.message);
+ });
+
+ it('testExtensions', function() {
+ var extension1 = new proto.jspb.test.IsExtension(['ext1field']);
+ var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2']]);
+ var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
+ extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1);
+ extendable.setExtension(proto.jspb.test.IndirectExtension.simple,
+ extension2);
+ extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy');
+ extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList,
+ ['a', 'b']);
+ var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]);
+ var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2']]);
+ extendable.setExtension(
+ proto.jspb.test.IndirectExtension.repeatedSimpleList,
+ [s1, s2]);
+ assertObjectEquals(extension1,
+ extendable.getExtension(proto.jspb.test.IsExtension.extField));
+ assertObjectEquals(extension2,
+ extendable.getExtension(proto.jspb.test.IndirectExtension.simple));
+ assertObjectEquals('xyzzy',
+ extendable.getExtension(proto.jspb.test.IndirectExtension.str));
+ assertObjectEquals(['a', 'b'], extendable.getExtension(
+ proto.jspb.test.IndirectExtension.repeatedStrList));
+ assertObjectEquals([s1, s2], extendable.getExtension(
+ proto.jspb.test.IndirectExtension.repeatedSimpleList));
+ // Not supported yet, but it should work...
+ extendable.setExtension(proto.jspb.test.IndirectExtension.simple, null);
+ assertNull(
+ extendable.getExtension(proto.jspb.test.IndirectExtension.simple));
+ extendable.setExtension(proto.jspb.test.IndirectExtension.str, null);
+ assertNull(extendable.getExtension(proto.jspb.test.IndirectExtension.str));
+
+
+ // Extension fields with jspb.ignore = true are ignored.
+ assertUndefined(proto.jspb.test.IndirectExtension['ignored']);
+ assertUndefined(proto.jspb.test.HasExtensions['ignoredFloating']);
+ });
+
+ it('testFloatingExtensions', function() {
+ // From an autogenerated container.
+ var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
+ var extension = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]);
+ extendable.setExtension(proto.jspb.test.simple1, extension);
+ assertObjectEquals(extension,
+ extendable.getExtension(proto.jspb.test.simple1));
+
+ // From _lib mode.
+ extension = new proto.jspb.test.ExtensionMessage(['s1']);
+ extendable = new proto.jspb.test.TestExtensionsMessage([16]);
+ extendable.setExtension(proto.jspb.test.floatingMsgField, extension);
+ extendable.setExtension(proto.jspb.test.floatingStrField, 's2');
+ assertObjectEquals(extension,
+ extendable.getExtension(proto.jspb.test.floatingMsgField));
+ assertObjectEquals('s2',
+ extendable.getExtension(proto.jspb.test.floatingStrField));
+ assertNotUndefined(proto.jspb.exttest.floatingMsgField);
+ assertNotUndefined(proto.jspb.exttest.floatingMsgFieldTwo);
+ assertNotUndefined(proto.jspb.exttest.beta.floatingStrField);
+ });
+
+ it('testToObject_extendedObject', function() {
+ var extension1 = new proto.jspb.test.IsExtension(['ext1field']);
+ var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2'], true]);
+ var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
+ extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1);
+ extendable.setExtension(proto.jspb.test.IndirectExtension.simple,
+ extension2);
+ extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy');
+ extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList,
+ ['a', 'b']);
+ var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2'], true]);
+ var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2'], false]);
+ extendable.setExtension(
+ proto.jspb.test.IndirectExtension.repeatedSimpleList,
+ [s1, s2]);
+ assertObjectEquals({
+ str1: 'v1', str2: 'v2', str3: 'v3',
+ extField: { ext1: 'ext1field' },
+ simple: {
+ aString: 'str', aRepeatedStringList: ['s1', 's2'], aBoolean: true
+ },
+ str: 'xyzzy',
+ repeatedStrList: ['a', 'b'],
+ repeatedSimpleList: [
+ { aString: 'foo', aRepeatedStringList: ['s1', 's2'], aBoolean: true},
+ { aString: 'bar', aRepeatedStringList: ['t1', 't2'], aBoolean: false}
+ ]
+ }, extendable.toObject());
+
+ // Now, with instances included.
+ assertObjectEquals({
+ str1: 'v1', str2: 'v2', str3: 'v3',
+ extField: {
+ ext1: 'ext1field',
+ $jspbMessageInstance:
+ extendable.getExtension(proto.jspb.test.IsExtension.extField)
+ },
+ simple: {
+ aString: 'str',
+ aRepeatedStringList: ['s1', 's2'],
+ aBoolean: true,
+ $jspbMessageInstance:
+ extendable.getExtension(proto.jspb.test.IndirectExtension.simple)
+ },
+ str: 'xyzzy',
+ repeatedStrList: ['a', 'b'],
+ repeatedSimpleList: [{
+ aString: 'foo',
+ aRepeatedStringList: ['s1', 's2'],
+ aBoolean: true,
+ $jspbMessageInstance: s1
+ }, {
+ aString: 'bar',
+ aRepeatedStringList: ['t1', 't2'],
+ aBoolean: false,
+ $jspbMessageInstance: s2
+ }],
+ $jspbMessageInstance: extendable
+ }, extendable.toObject(true /* opt_includeInstance */));
+ });
+
+ it('testInitialization_emptyArray', function() {
+ var msg = new proto.jspb.test.HasExtensions([]);
+ if (jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS) {
+ assertArrayEquals([], msg.toArray());
+ } else {
+ // Extension object is created past all regular fields.
+ assertArrayEquals([,,, {}], msg.toArray());
+ }
+ });
+
+ it('testInitialization_justExtensionObject', function() {
+ var msg = new proto.jspb.test.Empty([{1: 'hi'}]);
+ // The extensionObject is not moved from its original location.
+ assertArrayEquals([{1: 'hi'}], msg.toArray());
+ });
+
+ it('testInitialization_incompleteList', function() {
+ var msg = new proto.jspb.test.Empty([1, {4: 'hi'}]);
+ // The extensionObject is not moved from its original location.
+ assertArrayEquals([1, {4: 'hi'}], msg.toArray());
+ });
+
+ it('testInitialization_forwardCompatible', function() {
+ var msg = new proto.jspb.test.Empty([1, 2, 3, {1: 'hi'}]);
+ assertArrayEquals([1, 2, 3, {1: 'hi'}], msg.toArray());
+ });
+
+ it('testExtendedMessageEnsureObject',
+ /** @suppress {visibility} */ function() {
+ var data =
+ new proto.jspb.test.HasExtensions(['str1', {'a_key': 'an_object'}]);
+ assertEquals('an_object', data.extensionObject_['a_key']);
+ });
+
+ it('testToObject_hasExtensionField', function() {
+ var data = new proto.jspb.test.HasExtensions(['str1', {100: ['ext1']}]);
+ var obj = data.toObject();
+ assertEquals('str1', obj.str1);
+ assertEquals('ext1', obj.extField.ext1);
+ });
+
+ it('testGetExtension', function() {
+ var data = new proto.jspb.test.HasExtensions(['str1', {100: ['ext1']}]);
+ assertEquals('str1', data.getStr1());
+ var extension = data.getExtension(proto.jspb.test.IsExtension.extField);
+ assertNotNull(extension);
+ assertEquals('ext1', extension.getExt1());
+ });
+
+ it('testSetExtension', function() {
+ var data = new proto.jspb.test.HasExtensions();
+ var extensionMessage = new proto.jspb.test.IsExtension(['is_extension']);
+ data.setExtension(proto.jspb.test.IsExtension.extField, extensionMessage);
+ var obj = data.toObject();
+ assertNotNull(
+ data.getExtension(proto.jspb.test.IsExtension.extField));
+ assertEquals('is_extension', obj.extField.ext1);
+ });
+
+ /**
+ * Note that group is long deprecated, we only support it because JsPb has
+ * a goal of being able to generate JS classes for all proto descriptors.
+ */
+ it('testGroups', function() {
+ var group = new proto.jspb.test.TestGroup();
+ var someGroup = new proto.jspb.test.TestGroup.RepeatedGroup();
+ someGroup.setId('g1');
+ someGroup.setSomeBoolList([true, false]);
+ group.setRepeatedGroupList([someGroup]);
+ var groups = group.getRepeatedGroupList();
+ assertEquals('g1', groups[0].getId());
+ assertObjectEquals([true, false], groups[0].getSomeBoolList());
+ assertObjectEquals({id: 'g1', someBoolList: [true, false]},
+ groups[0].toObject());
+ assertObjectEquals({
+ repeatedGroupList: [{id: 'g1', someBoolList: [true, false]}],
+ requiredGroup: {id: undefined},
+ optionalGroup: undefined,
+ requiredSimple: {aRepeatedStringList: [], aString: undefined},
+ optionalSimple: undefined,
+ id: undefined
+ }, group.toObject());
+ var group1 = new proto.jspb.test.TestGroup1();
+ group1.setGroup(someGroup);
+ assertEquals(someGroup, group1.getGroup());
+ });
+
+ it('testNonExtensionFieldsAfterExtensionRange', function() {
+ var data = [{'1': 'a_string'}];
+ var message = new proto.jspb.test.Complex(data);
+ assertArrayEquals([], message.getARepeatedStringList());
+ });
+
+ it('testReservedGetterNames', function() {
+ var message = new proto.jspb.test.TestReservedNames();
+ message.setExtension$(11);
+ message.setExtension(proto.jspb.test.TestReservedNamesExtension.foo, 12);
+ assertEquals(11, message.getExtension$());
+ assertEquals(12, message.getExtension(
+ proto.jspb.test.TestReservedNamesExtension.foo));
+ assertObjectEquals({extension: 11, foo: 12}, message.toObject());
+ });
+
+ it('testInitializeMessageWithUnsetOneof', function() {
+ var message = new proto.jspb.test.TestMessageWithOneof([]);
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.PartialOneofCase.
+ PARTIAL_ONEOF_NOT_SET,
+ message.getPartialOneofCase());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.
+ RECURSIVE_ONEOF_NOT_SET,
+ message.getRecursiveOneofCase());
+ });
+
+ it('testInitializeMessageWithSingleValueSetInOneof', function() {
+ var message = new proto.jspb.test.TestMessageWithOneof([,, 'x']);
+
+ assertEquals('x', message.getPone());
+ assertEquals('', message.getPthree());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
+ message.getPartialOneofCase());
+ });
+
+ it('testKeepsLastWireValueSetInUnion_multipleValues', function() {
+ var message = new proto.jspb.test.TestMessageWithOneof([,, 'x',, 'y']);
+
+ assertEquals('', message.getPone());
+ assertEquals('y', message.getPthree());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE,
+ message.getPartialOneofCase());
+ });
+
+ it('testSettingOneofFieldClearsOthers', function() {
+ var message = new proto.jspb.test.TestMessageWithOneof;
+ assertEquals('', message.getPone());
+ assertEquals('', message.getPthree());
+ assertFalse(message.hasPone());
+ assertFalse(message.hasPthree());
+
+ message.setPone('hi');
+ assertEquals('hi', message.getPone());
+ assertEquals('', message.getPthree());
+ assertTrue(message.hasPone());
+ assertFalse(message.hasPthree());
+
+ message.setPthree('bye');
+ assertEquals('', message.getPone());
+ assertEquals('bye', message.getPthree());
+ assertFalse(message.hasPone());
+ assertTrue(message.hasPthree());
+ });
+
+ it('testSettingOneofFieldDoesNotClearFieldsFromOtherUnions', function() {
+ var other = new proto.jspb.test.TestMessageWithOneof;
+ var message = new proto.jspb.test.TestMessageWithOneof;
+ assertEquals('', message.getPone());
+ assertEquals('', message.getPthree());
+ assertUndefined(message.getRone());
+ assertFalse(message.hasPone());
+ assertFalse(message.hasPthree());
+
+ message.setPone('hi');
+ message.setRone(other);
+ assertEquals('hi', message.getPone());
+ assertEquals('', message.getPthree());
+ assertEquals(other, message.getRone());
+ assertTrue(message.hasPone());
+ assertFalse(message.hasPthree());
+
+ message.setPthree('bye');
+ assertEquals('', message.getPone());
+ assertEquals('bye', message.getPthree());
+ assertEquals(other, message.getRone());
+ assertFalse(message.hasPone());
+ assertTrue(message.hasPthree());
+ });
+
+ it('testUnsetsOneofCaseWhenFieldIsCleared', function() {
+ var message = new proto.jspb.test.TestMessageWithOneof;
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.PartialOneofCase.
+ PARTIAL_ONEOF_NOT_SET,
+ message.getPartialOneofCase());
+
+ message.setPone('hi');
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
+ message.getPartialOneofCase());
+
+ message.clearPone();
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.PartialOneofCase.
+ PARTIAL_ONEOF_NOT_SET,
+ message.getPartialOneofCase());
+ });
+
+ it('testMessageWithDefaultOneofValues', function() {
+ var message = new proto.jspb.test.TestMessageWithOneof;
+ assertEquals(1234, message.getAone());
+ assertEquals(0, message.getAtwo());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.DefaultOneofACase
+ .DEFAULT_ONEOF_A_NOT_SET,
+ message.getDefaultOneofACase());
+
+ message.setAone(567);
+ assertEquals(567, message.getAone());
+ assertEquals(0, message.getAtwo());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.AONE,
+ message.getDefaultOneofACase());
+
+ message.setAtwo(890);
+ assertEquals(1234, message.getAone());
+ assertEquals(890, message.getAtwo());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO,
+ message.getDefaultOneofACase());
+
+ message.clearAtwo();
+ assertEquals(1234, message.getAone());
+ assertEquals(0, message.getAtwo());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.DefaultOneofACase
+ .DEFAULT_ONEOF_A_NOT_SET,
+ message.getDefaultOneofACase());
+ });
+
+ it('testMessageWithDefaultOneofValues_defaultNotOnFirstField', function() {
+ var message = new proto.jspb.test.TestMessageWithOneof;
+ assertEquals(0, message.getBone());
+ assertEquals(1234, message.getBtwo());
+ assertFalse(message.hasBone());
+ assertFalse(message.hasBtwo());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase
+ .DEFAULT_ONEOF_B_NOT_SET,
+ message.getDefaultOneofBCase());
+
+ message.setBone(2);
+ assertEquals(2, message.getBone());
+ assertEquals(1234, message.getBtwo());
+ assertTrue(message.hasBone());
+ assertFalse(message.hasBtwo());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE,
+ message.getDefaultOneofBCase());
+
+ message.setBtwo(3);
+ assertEquals(0, message.getBone());
+ assertFalse(message.hasBone());
+ assertTrue(message.hasBtwo());
+ assertEquals(3, message.getBtwo());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
+ message.getDefaultOneofBCase());
+
+ message.clearBtwo();
+ assertEquals(0, message.getBone());
+ assertFalse(message.hasBone());
+ assertFalse(message.hasBtwo());
+ assertEquals(1234, message.getBtwo());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase
+ .DEFAULT_ONEOF_B_NOT_SET,
+ message.getDefaultOneofBCase());
+ });
+
+ it('testInitializeMessageWithOneofDefaults', function() {
+ var message =
+ new proto.jspb.test.TestMessageWithOneof(new Array(9).concat(567));
+ assertEquals(567, message.getAone());
+ assertEquals(0, message.getAtwo());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.AONE,
+ message.getDefaultOneofACase());
+
+ message =
+ new proto.jspb.test.TestMessageWithOneof(new Array(10).concat(890));
+ assertEquals(1234, message.getAone());
+ assertEquals(890, message.getAtwo());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO,
+ message.getDefaultOneofACase());
+
+ message =
+ new proto.jspb.test.TestMessageWithOneof(new Array(9).concat(567, 890));
+ assertEquals(1234, message.getAone());
+ assertEquals(890, message.getAtwo());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO,
+ message.getDefaultOneofACase());
+ });
+
+ it('testInitializeMessageWithOneofDefaults_defaultNotSetOnFirstField',
+ function() {
+ var message;
+
+ message =
+ new proto.jspb.test.TestMessageWithOneof(new Array(11).concat(567));
+ assertEquals(567, message.getBone());
+ assertEquals(1234, message.getBtwo());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE,
+ message.getDefaultOneofBCase());
+
+ message =
+ new proto.jspb.test.TestMessageWithOneof(new Array(12).concat(890));
+ assertEquals(0, message.getBone());
+ assertEquals(890, message.getBtwo());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
+ message.getDefaultOneofBCase());
+
+ message = new proto.jspb.test.TestMessageWithOneof(
+ new Array(11).concat(567, 890));
+ assertEquals(0, message.getBone());
+ assertEquals(890, message.getBtwo());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
+ message.getDefaultOneofBCase());
+ });
+
+ it('testOneofContainingAnotherMessage', function() {
+ var message = new proto.jspb.test.TestMessageWithOneof;
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.
+ RECURSIVE_ONEOF_NOT_SET,
+ message.getRecursiveOneofCase());
+
+ var other = new proto.jspb.test.TestMessageWithOneof;
+ message.setRone(other);
+ assertEquals(other, message.getRone());
+ assertEquals('', message.getRtwo());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.RONE,
+ message.getRecursiveOneofCase());
+
+ message.setRtwo('hi');
+ assertUndefined(message.getRone());
+ assertEquals('hi', message.getRtwo());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.RTWO,
+ message.getRecursiveOneofCase());
+ });
+
+ it('testQueryingOneofCaseEnsuresOnlyOneFieldIsSetInUnderlyingArray',
+ function() {
+ var message = new proto.jspb.test.TestMessageWithOneof;
+ message.setPone('x');
+ assertEquals('x', message.getPone());
+ assertEquals('', message.getPthree());
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
+ message.getPartialOneofCase());
+
+ var array = message.toArray();
+ assertEquals('x', array[2]);
+ assertUndefined(array[4]);
+ array[4] = 'y';
+
+ assertEquals(
+ proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE,
+ message.getPartialOneofCase());
+ assertUndefined(array[2]);
+ assertEquals('y', array[4]);
+ });
+
+ it('testFloatingPointFieldsSupportNan', function() {
+ var assertNan = function(x) {
+ assertTrue('Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.',
+ goog.isNumber(x) && isNaN(x));
+ };
+
+ var message = new proto.jspb.test.FloatingPointFields([
+ 'NaN', 'NaN', ['NaN', 'NaN'], 'NaN',
+ 'NaN', 'NaN', ['NaN', 'NaN'], 'NaN'
+ ]);
+ assertNan(message.getOptionalFloatField());
+ assertNan(message.getRequiredFloatField());
+ assertNan(message.getRepeatedFloatFieldList()[0]);
+ assertNan(message.getRepeatedFloatFieldList()[1]);
+ assertNan(message.getDefaultFloatField());
+ assertNan(message.getOptionalDoubleField());
+ assertNan(message.getRequiredDoubleField());
+ assertNan(message.getRepeatedDoubleFieldList()[0]);
+ assertNan(message.getRepeatedDoubleFieldList()[1]);
+ assertNan(message.getDefaultDoubleField());
+ });
+
+});
diff --git a/js/compatibility_tests/v3.1.0/proto3_test.js b/js/compatibility_tests/v3.1.0/proto3_test.js
new file mode 100644
index 00000000..3c929eff
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/proto3_test.js
@@ -0,0 +1,329 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+goog.require('goog.crypt.base64');
+goog.require('goog.testing.asserts');
+
+// CommonJS-LoadFromFile: testbinary_pb proto.jspb.test
+goog.require('proto.jspb.test.ForeignMessage');
+
+// CommonJS-LoadFromFile: proto3_test_pb proto.jspb.test
+goog.require('proto.jspb.test.Proto3Enum');
+goog.require('proto.jspb.test.TestProto3');
+
+
+var BYTES = new Uint8Array([1, 2, 8, 9]);
+var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES);
+
+
+/**
+ * Helper: compare a bytes field to an expected value
+ * @param {Uint8Array|string} arr
+ * @param {Uint8Array} expected
+ * @return {boolean}
+ */
+function bytesCompare(arr, expected) {
+ if (goog.isString(arr)) {
+ arr = goog.crypt.base64.decodeStringToUint8Array(arr);
+ }
+ if (arr.length != expected.length) {
+ return false;
+ }
+ for (var i = 0; i < arr.length; i++) {
+ if (arr[i] != expected[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+describe('proto3Test', function() {
+ /**
+ * Test defaults for proto3 message fields.
+ */
+ it('testProto3FieldDefaults', function() {
+ var msg = new proto.jspb.test.TestProto3();
+
+ assertEquals(msg.getOptionalInt32(), 0);
+ assertEquals(msg.getOptionalInt64(), 0);
+ assertEquals(msg.getOptionalUint32(), 0);
+ assertEquals(msg.getOptionalUint64(), 0);
+ assertEquals(msg.getOptionalSint32(), 0);
+ assertEquals(msg.getOptionalSint64(), 0);
+ assertEquals(msg.getOptionalFixed32(), 0);
+ assertEquals(msg.getOptionalFixed64(), 0);
+ assertEquals(msg.getOptionalSfixed32(), 0);
+ assertEquals(msg.getOptionalSfixed64(), 0);
+ assertEquals(msg.getOptionalFloat(), 0);
+ assertEquals(msg.getOptionalDouble(), 0);
+ assertEquals(msg.getOptionalString(), '');
+
+ // TODO(b/26173701): when we change bytes fields default getter to return
+ // Uint8Array, we'll want to switch this assertion to match the u8 case.
+ assertEquals(typeof msg.getOptionalBytes(), 'string');
+ assertEquals(msg.getOptionalBytes_asU8() instanceof Uint8Array, true);
+ assertEquals(typeof msg.getOptionalBytes_asB64(), 'string');
+ assertEquals(msg.getOptionalBytes().length, 0);
+ assertEquals(msg.getOptionalBytes_asU8().length, 0);
+ assertEquals(msg.getOptionalBytes_asB64(), '');
+
+ assertEquals(msg.getOptionalForeignEnum(),
+ proto.jspb.test.Proto3Enum.PROTO3_FOO);
+ assertEquals(msg.getOptionalForeignMessage(), undefined);
+ assertEquals(msg.getOptionalForeignMessage(), undefined);
+
+ assertEquals(msg.getRepeatedInt32List().length, 0);
+ assertEquals(msg.getRepeatedInt64List().length, 0);
+ assertEquals(msg.getRepeatedUint32List().length, 0);
+ assertEquals(msg.getRepeatedUint64List().length, 0);
+ assertEquals(msg.getRepeatedSint32List().length, 0);
+ assertEquals(msg.getRepeatedSint64List().length, 0);
+ assertEquals(msg.getRepeatedFixed32List().length, 0);
+ assertEquals(msg.getRepeatedFixed64List().length, 0);
+ assertEquals(msg.getRepeatedSfixed32List().length, 0);
+ assertEquals(msg.getRepeatedSfixed64List().length, 0);
+ assertEquals(msg.getRepeatedFloatList().length, 0);
+ assertEquals(msg.getRepeatedDoubleList().length, 0);
+ assertEquals(msg.getRepeatedStringList().length, 0);
+ assertEquals(msg.getRepeatedBytesList().length, 0);
+ assertEquals(msg.getRepeatedForeignEnumList().length, 0);
+ assertEquals(msg.getRepeatedForeignMessageList().length, 0);
+
+ });
+
+
+ /**
+ * Test that all fields can be set and read via a serialization roundtrip.
+ */
+ it('testProto3FieldSetGet', function() {
+ var msg = new proto.jspb.test.TestProto3();
+
+ msg.setOptionalInt32(-42);
+ msg.setOptionalInt64(-0x7fffffff00000000);
+ msg.setOptionalUint32(0x80000000);
+ msg.setOptionalUint64(0xf000000000000000);
+ msg.setOptionalSint32(-100);
+ msg.setOptionalSint64(-0x8000000000000000);
+ msg.setOptionalFixed32(1234);
+ msg.setOptionalFixed64(0x1234567800000000);
+ msg.setOptionalSfixed32(-1234);
+ msg.setOptionalSfixed64(-0x1234567800000000);
+ msg.setOptionalFloat(1.5);
+ msg.setOptionalDouble(-1.5);
+ msg.setOptionalBool(true);
+ msg.setOptionalString('hello world');
+ msg.setOptionalBytes(BYTES);
+ var submsg = new proto.jspb.test.ForeignMessage();
+ submsg.setC(16);
+ msg.setOptionalForeignMessage(submsg);
+ msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR);
+
+ msg.setRepeatedInt32List([-42]);
+ msg.setRepeatedInt64List([-0x7fffffff00000000]);
+ msg.setRepeatedUint32List([0x80000000]);
+ msg.setRepeatedUint64List([0xf000000000000000]);
+ msg.setRepeatedSint32List([-100]);
+ msg.setRepeatedSint64List([-0x8000000000000000]);
+ msg.setRepeatedFixed32List([1234]);
+ msg.setRepeatedFixed64List([0x1234567800000000]);
+ msg.setRepeatedSfixed32List([-1234]);
+ msg.setRepeatedSfixed64List([-0x1234567800000000]);
+ msg.setRepeatedFloatList([1.5]);
+ msg.setRepeatedDoubleList([-1.5]);
+ msg.setRepeatedBoolList([true]);
+ msg.setRepeatedStringList(['hello world']);
+ msg.setRepeatedBytesList([BYTES]);
+ submsg = new proto.jspb.test.ForeignMessage();
+ submsg.setC(1000);
+ msg.setRepeatedForeignMessageList([submsg]);
+ msg.setRepeatedForeignEnumList([proto.jspb.test.Proto3Enum.PROTO3_BAR]);
+
+ msg.setOneofString('asdf');
+
+ var serialized = msg.serializeBinary();
+ msg = proto.jspb.test.TestProto3.deserializeBinary(serialized);
+
+ assertEquals(msg.getOptionalInt32(), -42);
+ assertEquals(msg.getOptionalInt64(), -0x7fffffff00000000);
+ assertEquals(msg.getOptionalUint32(), 0x80000000);
+ assertEquals(msg.getOptionalUint64(), 0xf000000000000000);
+ assertEquals(msg.getOptionalSint32(), -100);
+ assertEquals(msg.getOptionalSint64(), -0x8000000000000000);
+ assertEquals(msg.getOptionalFixed32(), 1234);
+ assertEquals(msg.getOptionalFixed64(), 0x1234567800000000);
+ assertEquals(msg.getOptionalSfixed32(), -1234);
+ assertEquals(msg.getOptionalSfixed64(), -0x1234567800000000);
+ assertEquals(msg.getOptionalFloat(), 1.5);
+ assertEquals(msg.getOptionalDouble(), -1.5);
+ assertEquals(msg.getOptionalBool(), true);
+ assertEquals(msg.getOptionalString(), 'hello world');
+ assertEquals(true, bytesCompare(msg.getOptionalBytes(), BYTES));
+ assertEquals(msg.getOptionalForeignMessage().getC(), 16);
+ assertEquals(msg.getOptionalForeignEnum(),
+ proto.jspb.test.Proto3Enum.PROTO3_BAR);
+
+ assertElementsEquals(msg.getRepeatedInt32List(), [-42]);
+ assertElementsEquals(msg.getRepeatedInt64List(), [-0x7fffffff00000000]);
+ assertElementsEquals(msg.getRepeatedUint32List(), [0x80000000]);
+ assertElementsEquals(msg.getRepeatedUint64List(), [0xf000000000000000]);
+ assertElementsEquals(msg.getRepeatedSint32List(), [-100]);
+ assertElementsEquals(msg.getRepeatedSint64List(), [-0x8000000000000000]);
+ assertElementsEquals(msg.getRepeatedFixed32List(), [1234]);
+ assertElementsEquals(msg.getRepeatedFixed64List(), [0x1234567800000000]);
+ assertElementsEquals(msg.getRepeatedSfixed32List(), [-1234]);
+ assertElementsEquals(msg.getRepeatedSfixed64List(), [-0x1234567800000000]);
+ assertElementsEquals(msg.getRepeatedFloatList(), [1.5]);
+ assertElementsEquals(msg.getRepeatedDoubleList(), [-1.5]);
+ assertElementsEquals(msg.getRepeatedBoolList(), [true]);
+ assertElementsEquals(msg.getRepeatedStringList(), ['hello world']);
+ assertEquals(msg.getRepeatedBytesList().length, 1);
+ assertEquals(true, bytesCompare(msg.getRepeatedBytesList()[0], BYTES));
+ assertEquals(msg.getRepeatedForeignMessageList().length, 1);
+ assertEquals(msg.getRepeatedForeignMessageList()[0].getC(), 1000);
+ assertElementsEquals(msg.getRepeatedForeignEnumList(),
+ [proto.jspb.test.Proto3Enum.PROTO3_BAR]);
+
+ assertEquals(msg.getOneofString(), 'asdf');
+ });
+
+
+ /**
+ * Test that oneofs continue to have a notion of field presence.
+ */
+ it('testOneofs', function() {
+ var msg = new proto.jspb.test.TestProto3();
+
+ assertEquals(msg.getOneofUint32(), 0);
+ assertEquals(msg.getOneofForeignMessage(), undefined);
+ assertEquals(msg.getOneofString(), '');
+ assertEquals(msg.getOneofBytes(), '');
+ assertFalse(msg.hasOneofUint32());
+ assertFalse(msg.hasOneofString());
+ assertFalse(msg.hasOneofBytes());
+
+ msg.setOneofUint32(42);
+ assertEquals(msg.getOneofUint32(), 42);
+ assertEquals(msg.getOneofForeignMessage(), undefined);
+ assertEquals(msg.getOneofString(), '');
+ assertEquals(msg.getOneofBytes(), '');
+ assertTrue(msg.hasOneofUint32());
+ assertFalse(msg.hasOneofString());
+ assertFalse(msg.hasOneofBytes());
+
+
+ var submsg = new proto.jspb.test.ForeignMessage();
+ msg.setOneofForeignMessage(submsg);
+ assertEquals(msg.getOneofUint32(), 0);
+ assertEquals(msg.getOneofForeignMessage(), submsg);
+ assertEquals(msg.getOneofString(), '');
+ assertEquals(msg.getOneofBytes(), '');
+ assertFalse(msg.hasOneofUint32());
+ assertFalse(msg.hasOneofString());
+ assertFalse(msg.hasOneofBytes());
+
+ msg.setOneofString('hello');
+ assertEquals(msg.getOneofUint32(), 0);
+ assertEquals(msg.getOneofForeignMessage(), undefined);
+ assertEquals(msg.getOneofString(), 'hello');
+ assertEquals(msg.getOneofBytes(), '');
+ assertFalse(msg.hasOneofUint32());
+ assertTrue(msg.hasOneofString());
+ assertFalse(msg.hasOneofBytes());
+
+ msg.setOneofBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
+ assertEquals(msg.getOneofUint32(), 0);
+ assertEquals(msg.getOneofForeignMessage(), undefined);
+ assertEquals(msg.getOneofString(), '');
+ assertEquals(msg.getOneofBytes_asB64(),
+ goog.crypt.base64.encodeString('\u00FF\u00FF'));
+ assertFalse(msg.hasOneofUint32());
+ assertFalse(msg.hasOneofString());
+ assertTrue(msg.hasOneofBytes());
+ });
+
+
+ /**
+ * Test that "default"-valued primitive fields are not emitted on the wire.
+ */
+ it('testNoSerializeDefaults', function() {
+ var msg = new proto.jspb.test.TestProto3();
+
+ // Set each primitive to a non-default value, then back to its default, to
+ // ensure that the serialization is actually checking the value and not just
+ // whether it has ever been set.
+ msg.setOptionalInt32(42);
+ msg.setOptionalInt32(0);
+ msg.setOptionalDouble(3.14);
+ msg.setOptionalDouble(0.0);
+ msg.setOptionalBool(true);
+ msg.setOptionalBool(false);
+ msg.setOptionalString('hello world');
+ msg.setOptionalString('');
+ msg.setOptionalBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
+ msg.setOptionalBytes('');
+ msg.setOptionalForeignMessage(new proto.jspb.test.ForeignMessage());
+ msg.setOptionalForeignMessage(null);
+ msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR);
+ msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_FOO);
+ msg.setOneofUint32(32);
+ msg.clearOneofUint32();
+
+
+ var serialized = msg.serializeBinary();
+ assertEquals(0, serialized.length);
+ });
+
+ /**
+ * Test that base64 string and Uint8Array are interchangeable in bytes fields.
+ */
+ it('testBytesFieldsInterop', function() {
+ var msg = new proto.jspb.test.TestProto3();
+ // Set as a base64 string and check all the getters work.
+ msg.setOptionalBytes(BYTES_B64);
+ assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+ assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+ assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+ // Test binary serialize round trip doesn't break it.
+ msg = proto.jspb.test.TestProto3.deserializeBinary(msg.serializeBinary());
+ assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+ assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+ assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+ msg = new proto.jspb.test.TestProto3();
+ // Set as a Uint8Array and check all the getters work.
+ msg.setOptionalBytes(BYTES);
+ assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+ assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+ assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+ });
+});
diff --git a/js/compatibility_tests/v3.1.0/proto3_test.proto b/js/compatibility_tests/v3.1.0/proto3_test.proto
new file mode 100644
index 00000000..acb67164
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/proto3_test.proto
@@ -0,0 +1,89 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+import "testbinary.proto";
+
+package jspb.test;
+
+message TestProto3 {
+ int32 optional_int32 = 1;
+ int64 optional_int64 = 2;
+ uint32 optional_uint32 = 3;
+ uint64 optional_uint64 = 4;
+ sint32 optional_sint32 = 5;
+ sint64 optional_sint64 = 6;
+ fixed32 optional_fixed32 = 7;
+ fixed64 optional_fixed64 = 8;
+ sfixed32 optional_sfixed32 = 9;
+ sfixed64 optional_sfixed64 = 10;
+ float optional_float = 11;
+ double optional_double = 12;
+ bool optional_bool = 13;
+ string optional_string = 14;
+ bytes optional_bytes = 15;
+
+ ForeignMessage optional_foreign_message = 19;
+ Proto3Enum optional_foreign_enum = 22;
+
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+
+ repeated ForeignMessage repeated_foreign_message = 49;
+ repeated Proto3Enum repeated_foreign_enum = 52;
+
+
+ oneof oneof_field {
+ uint32 oneof_uint32 = 111;
+ ForeignMessage oneof_foreign_message = 112;
+ string oneof_string = 113;
+ bytes oneof_bytes = 114;
+ }
+}
+
+enum Proto3Enum {
+ PROTO3_FOO = 0;
+ PROTO3_BAR = 1;
+ PROTO3_BAZ = 2;
+}
diff --git a/js/compatibility_tests/v3.1.0/test.proto b/js/compatibility_tests/v3.1.0/test.proto
new file mode 100644
index 00000000..48cb37e1
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/test.proto
@@ -0,0 +1,262 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: mwr@google.com (Mark Rawling)
+
+syntax = "proto2";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+import "google/protobuf/descriptor.proto";
+
+package jspb.test;
+
+message Empty {
+}
+
+enum OuterEnum {
+ FOO = 1;
+ BAR = 2;
+}
+
+message EnumContainer {
+ optional OuterEnum outer_enum = 1;
+}
+
+message Simple1 {
+ required string a_string = 1;
+ repeated string a_repeated_string = 2;
+ optional bool a_boolean = 3;
+}
+
+// A message that differs from Simple1 only by name
+message Simple2 {
+ required string a_string = 1;
+ repeated string a_repeated_string = 2;
+}
+
+message SpecialCases {
+ required string normal = 1;
+ // Examples of Js reserved names that are converted to pb_<name>.
+ required string default = 2;
+ required string function = 3;
+ required string var = 4;
+}
+
+message OptionalFields {
+ message Nested {
+ optional int32 an_int = 1;
+ }
+ optional string a_string = 1;
+ required bool a_bool = 2;
+ optional Nested a_nested_message = 3;
+ repeated Nested a_repeated_message = 4;
+ repeated string a_repeated_string = 5;
+}
+
+message HasExtensions {
+ optional string str1 = 1;
+ optional string str2 = 2;
+ optional string str3 = 3;
+ extensions 10 to max;
+}
+
+message Complex {
+ message Nested {
+ required int32 an_int = 2;
+ }
+ required string a_string = 1;
+ required bool an_out_of_order_bool = 9;
+ optional Nested a_nested_message = 4;
+ repeated Nested a_repeated_message = 5;
+ repeated string a_repeated_string = 7;
+}
+
+message OuterMessage {
+ // Make sure this doesn't conflict with the other Complex message.
+ message Complex {
+ optional int32 inner_complex_field = 1;
+ }
+}
+
+message IsExtension {
+ extend HasExtensions {
+ optional IsExtension ext_field = 100;
+ }
+ optional string ext1 = 1;
+
+ // Extensions of proto2 Descriptor messages will be ignored.
+ extend google.protobuf.EnumOptions {
+ optional string simple_option = 42113038;
+ }
+}
+
+message IndirectExtension {
+ extend HasExtensions {
+ optional Simple1 simple = 101;
+ optional string str = 102;
+ repeated string repeated_str = 103;
+ repeated Simple1 repeated_simple = 104;
+ }
+}
+
+extend HasExtensions {
+ optional Simple1 simple1 = 105;
+}
+
+message DefaultValues {
+ enum Enum {
+ E1 = 13;
+ E2 = 77;
+ }
+ optional string string_field = 1 [default="default<>\'\"abc"];
+ optional bool bool_field = 2 [default=true];
+ optional int64 int_field = 3 [default=11];
+ optional Enum enum_field = 4 [default=E1];
+ optional string empty_field = 6 [default=""];
+ optional bytes bytes_field = 8 [default="moo"]; // Base64 encoding is "bW9v"
+}
+
+message FloatingPointFields {
+ optional float optional_float_field = 1;
+ required float required_float_field = 2;
+ repeated float repeated_float_field = 3;
+ optional float default_float_field = 4 [default = 2.0];
+ optional double optional_double_field = 5;
+ required double required_double_field = 6;
+ repeated double repeated_double_field = 7;
+ optional double default_double_field = 8 [default = 2.0];
+}
+
+message TestClone {
+ optional string str = 1;
+ optional Simple1 simple1 = 3;
+ repeated Simple1 simple2 = 5;
+ optional bytes bytes_field = 6;
+ optional string unused = 7;
+ extensions 10 to max;
+}
+
+message CloneExtension {
+ extend TestClone {
+ optional CloneExtension ext_field = 100;
+ }
+ optional string ext = 2;
+}
+
+message TestGroup {
+ repeated group RepeatedGroup = 1 {
+ required string id = 1;
+ repeated bool some_bool = 2;
+ }
+ required group RequiredGroup = 2 {
+ required string id = 1;
+ }
+ optional group OptionalGroup = 3 {
+ required string id = 1;
+ }
+ optional string id = 4;
+ required Simple2 required_simple = 5;
+ optional Simple2 optional_simple = 6;
+}
+
+message TestGroup1 {
+ optional TestGroup.RepeatedGroup group = 1;
+}
+
+message TestReservedNames {
+ optional int32 extension = 1;
+ extensions 10 to max;
+}
+
+message TestReservedNamesExtension {
+ extend TestReservedNames {
+ optional int32 foo = 10;
+ }
+}
+
+message TestMessageWithOneof {
+
+ oneof partial_oneof {
+ string pone = 3;
+ string pthree = 5;
+ }
+
+ oneof recursive_oneof {
+ TestMessageWithOneof rone = 6;
+ string rtwo = 7;
+ }
+
+ optional bool normal_field = 8;
+ repeated string repeated_field = 9;
+
+ oneof default_oneof_a {
+ int32 aone = 10 [default = 1234];
+ int32 atwo = 11;
+ }
+
+ oneof default_oneof_b {
+ int32 bone = 12;
+ int32 btwo = 13 [default = 1234];
+ }
+}
+
+message TestEndsWithBytes {
+ optional int32 value = 1;
+ optional bytes data = 2;
+}
+
+message TestMapFieldsNoBinary {
+ map<string, string> map_string_string = 1;
+ map<string, int32> map_string_int32 = 2;
+ map<string, int64> map_string_int64 = 3;
+ map<string, bool> map_string_bool = 4;
+ map<string, double> map_string_double = 5;
+ map<string, MapValueEnumNoBinary> map_string_enum = 6;
+ map<string, MapValueMessageNoBinary> map_string_msg = 7;
+
+ map<int32, string> map_int32_string = 8;
+ map<int64, string> map_int64_string = 9;
+ map<bool, string> map_bool_string = 10;
+
+ optional TestMapFieldsNoBinary test_map_fields = 11;
+ map<string, TestMapFieldsNoBinary> map_string_testmapfields = 12;
+}
+
+enum MapValueEnumNoBinary {
+ MAP_VALUE_FOO_NOBINARY = 0;
+ MAP_VALUE_BAR_NOBINARY = 1;
+ MAP_VALUE_BAZ_NOBINARY = 2;
+}
+
+message MapValueMessageNoBinary {
+ optional int32 foo = 1;
+}
diff --git a/js/compatibility_tests/v3.1.0/test2.proto b/js/compatibility_tests/v3.1.0/test2.proto
new file mode 100644
index 00000000..44e55eff
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/test2.proto
@@ -0,0 +1,54 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.test;
+
+message TestExtensionsMessage {
+ optional int32 intfield = 1;
+ extensions 100 to max;
+}
+
+message ExtensionMessage {
+ extend TestExtensionsMessage {
+ optional ExtensionMessage ext_field = 100;
+ }
+ optional string ext1 = 1;
+}
+
+// Floating extensions are only supported when generating a _lib.js library.
+extend TestExtensionsMessage {
+ optional ExtensionMessage floating_msg_field = 101;
+ optional string floating_str_field = 102;
+}
diff --git a/js/compatibility_tests/v3.1.0/test3.proto b/js/compatibility_tests/v3.1.0/test3.proto
new file mode 100644
index 00000000..940a552e
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/test3.proto
@@ -0,0 +1,53 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.exttest;
+
+message TestExtensionsMessage {
+ optional int32 intfield = 1;
+ extensions 100 to max;
+}
+
+message ExtensionMessage {
+ extend TestExtensionsMessage {
+ optional ExtensionMessage ext_field = 100;
+ }
+ optional string ext1 = 1;
+}
+
+extend TestExtensionsMessage {
+ optional ExtensionMessage floating_msg_field = 101;
+ optional string floating_str_field = 102;
+}
diff --git a/js/compatibility_tests/v3.1.0/test4.proto b/js/compatibility_tests/v3.1.0/test4.proto
new file mode 100644
index 00000000..cf2451e9
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/test4.proto
@@ -0,0 +1,42 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.exttest;
+
+import "test3.proto";
+
+extend TestExtensionsMessage {
+ optional ExtensionMessage floating_msg_field_two = 103;
+}
diff --git a/js/compatibility_tests/v3.1.0/test5.proto b/js/compatibility_tests/v3.1.0/test5.proto
new file mode 100644
index 00000000..34979517
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/test5.proto
@@ -0,0 +1,44 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.exttest.beta;
+
+message TestBetaExtensionsMessage {
+ extensions 100 to max;
+}
+
+extend TestBetaExtensionsMessage {
+ optional string floating_str_field = 101;
+}
diff --git a/js/compatibility_tests/v3.1.0/testbinary.proto b/js/compatibility_tests/v3.1.0/testbinary.proto
new file mode 100644
index 00000000..116f17fb
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/testbinary.proto
@@ -0,0 +1,212 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// LINT: ALLOW_GROUPS
+
+syntax = "proto2";
+
+
+package jspb.test;
+
+// These types are borrowed from `unittest.proto` in the protobuf tree. We want
+// to ensure that the binary-format support will handle all field types
+// properly.
+message TestAllTypes {
+ optional int32 optional_int32 = 1;
+ optional int64 optional_int64 = 2;
+ optional uint32 optional_uint32 = 3;
+ optional uint64 optional_uint64 = 4;
+ optional sint32 optional_sint32 = 5;
+ optional sint64 optional_sint64 = 6;
+ optional fixed32 optional_fixed32 = 7;
+ optional fixed64 optional_fixed64 = 8;
+ optional sfixed32 optional_sfixed32 = 9;
+ optional sfixed64 optional_sfixed64 = 10;
+ optional float optional_float = 11;
+ optional double optional_double = 12;
+ optional bool optional_bool = 13;
+ optional string optional_string = 14;
+ optional bytes optional_bytes = 15;
+ optional group OptionalGroup = 16 {
+ optional int32 a = 17;
+ }
+
+ optional ForeignMessage optional_foreign_message = 19;
+ optional ForeignEnum optional_foreign_enum = 22;
+
+ // Repeated
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+
+ repeated group RepeatedGroup = 46 {
+ optional int32 a = 47;
+ }
+
+ repeated ForeignMessage repeated_foreign_message = 49;
+ repeated ForeignEnum repeated_foreign_enum = 52;
+
+ // Packed repeated
+ repeated int32 packed_repeated_int32 = 61 [packed=true];
+ repeated int64 packed_repeated_int64 = 62 [packed=true];
+ repeated uint32 packed_repeated_uint32 = 63 [packed=true];
+ repeated uint64 packed_repeated_uint64 = 64 [packed=true];
+ repeated sint32 packed_repeated_sint32 = 65 [packed=true];
+ repeated sint64 packed_repeated_sint64 = 66 [packed=true];
+ repeated fixed32 packed_repeated_fixed32 = 67 [packed=true];
+ repeated fixed64 packed_repeated_fixed64 = 68 [packed=true];
+ repeated sfixed32 packed_repeated_sfixed32 = 69 [packed=true];
+ repeated sfixed64 packed_repeated_sfixed64 = 70 [packed=true];
+ repeated float packed_repeated_float = 71 [packed=true];
+ repeated double packed_repeated_double = 72 [packed=true];
+ repeated bool packed_repeated_bool = 73 [packed=true];
+
+ oneof oneof_field {
+ uint32 oneof_uint32 = 111;
+ ForeignMessage oneof_foreign_message = 112;
+ string oneof_string = 113;
+ bytes oneof_bytes = 114;
+ }
+
+}
+
+message ForeignMessage {
+ optional int32 c = 1;
+}
+
+enum ForeignEnum {
+ FOREIGN_FOO = 4;
+ FOREIGN_BAR = 5;
+ FOREIGN_BAZ = 6;
+}
+
+message TestExtendable {
+ extensions 1 to max;
+}
+
+message ExtendsWithMessage {
+ extend TestExtendable {
+ optional ExtendsWithMessage optional_extension = 19;
+ repeated ExtendsWithMessage repeated_extension = 49;
+ }
+ optional int32 foo = 1;
+}
+
+extend TestExtendable {
+ optional int32 extend_optional_int32 = 1;
+ optional int64 extend_optional_int64 = 2;
+ optional uint32 extend_optional_uint32 = 3;
+ optional uint64 extend_optional_uint64 = 4;
+ optional sint32 extend_optional_sint32 = 5;
+ optional sint64 extend_optional_sint64 = 6;
+ optional fixed32 extend_optional_fixed32 = 7;
+ optional fixed64 extend_optional_fixed64 = 8;
+ optional sfixed32 extend_optional_sfixed32 = 9;
+ optional sfixed64 extend_optional_sfixed64 = 10;
+ optional float extend_optional_float = 11;
+ optional double extend_optional_double = 12;
+ optional bool extend_optional_bool = 13;
+ optional string extend_optional_string = 14;
+ optional bytes extend_optional_bytes = 15;
+ optional ForeignEnum extend_optional_foreign_enum = 22;
+
+ repeated int32 extend_repeated_int32 = 31;
+ repeated int64 extend_repeated_int64 = 32;
+ repeated uint32 extend_repeated_uint32 = 33;
+ repeated uint64 extend_repeated_uint64 = 34;
+ repeated sint32 extend_repeated_sint32 = 35;
+ repeated sint64 extend_repeated_sint64 = 36;
+ repeated fixed32 extend_repeated_fixed32 = 37;
+ repeated fixed64 extend_repeated_fixed64 = 38;
+ repeated sfixed32 extend_repeated_sfixed32 = 39;
+ repeated sfixed64 extend_repeated_sfixed64 = 40;
+ repeated float extend_repeated_float = 41;
+ repeated double extend_repeated_double = 42;
+ repeated bool extend_repeated_bool = 43;
+ repeated string extend_repeated_string = 44;
+ repeated bytes extend_repeated_bytes = 45;
+ repeated ForeignEnum extend_repeated_foreign_enum = 52;
+
+ repeated int32 extend_packed_repeated_int32 = 61 [packed=true];
+ repeated int64 extend_packed_repeated_int64 = 62 [packed=true];
+ repeated uint32 extend_packed_repeated_uint32 = 63 [packed=true];
+ repeated uint64 extend_packed_repeated_uint64 = 64 [packed=true];
+ repeated sint32 extend_packed_repeated_sint32 = 65 [packed=true];
+ repeated sint64 extend_packed_repeated_sint64 = 66 [packed=true];
+ repeated fixed32 extend_packed_repeated_fixed32 = 67 [packed=true];
+ repeated fixed64 extend_packed_repeated_fixed64 = 68 [packed=true];
+ repeated sfixed32 extend_packed_repeated_sfixed32 = 69 [packed=true];
+ repeated sfixed64 extend_packed_repeated_sfixed64 = 70 [packed=true];
+ repeated float extend_packed_repeated_float = 71 [packed=true];
+ repeated double extend_packed_repeated_double = 72 [packed=true];
+ repeated bool extend_packed_repeated_bool = 73 [packed=true];
+ repeated ForeignEnum extend_packed_repeated_foreign_enum = 82
+ [packed=true];
+
+}
+
+message TestMapFields {
+ map<string, string> map_string_string = 1;
+ map<string, int32> map_string_int32 = 2;
+ map<string, int64> map_string_int64 = 3;
+ map<string, bool> map_string_bool = 4;
+ map<string, double> map_string_double = 5;
+ map<string, MapValueEnum> map_string_enum = 6;
+ map<string, MapValueMessage> map_string_msg = 7;
+
+ map<int32, string> map_int32_string = 8;
+ map<int64, string> map_int64_string = 9;
+ map<bool, string> map_bool_string = 10;
+
+ optional TestMapFields test_map_fields = 11;
+ map<string, TestMapFields> map_string_testmapfields = 12;
+}
+
+enum MapValueEnum {
+ MAP_VALUE_FOO = 0;
+ MAP_VALUE_BAR = 1;
+ MAP_VALUE_BAZ = 2;
+}
+
+message MapValueMessage {
+ optional int32 foo = 1;
+}
diff --git a/js/compatibility_tests/v3.1.0/testempty.proto b/js/compatibility_tests/v3.1.0/testempty.proto
new file mode 100644
index 00000000..960bce4e
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/testempty.proto
@@ -0,0 +1,34 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package javatests.com.google.apps.jspb;
+
diff --git a/js/message.js b/js/message.js
index 1f6bf16b..f7dcfa96 100644
--- a/js/message.js
+++ b/js/message.js
@@ -41,7 +41,6 @@ goog.provide('jspb.Message');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.crypt.base64');
-goog.require('goog.json');
goog.require('jspb.Map');
// Not needed in compilation units that have no protos with xids.
@@ -192,8 +191,8 @@ goog.define('jspb.Message.GENERATE_FROM_OBJECT', !goog.DISALLOW_TEST_ONLY_CODE);
/**
* @define {boolean} Whether to generate toString methods for objects. Turn
- * this off if you do use toString in your project and want to trim it from
- * compiled JS.
+ * this off if you do not use toString in your project and want to trim it
+ * from the compiled JS.
*/
goog.define('jspb.Message.GENERATE_TO_STRING', true);
@@ -351,7 +350,7 @@ jspb.Message.initialize = function(
// which would otherwise go unused.
msg.arrayIndexOffset_ = messageId === 0 ? -1 : 0;
msg.array = data;
- jspb.Message.materializeExtensionObject_(msg, suggestedPivot);
+ jspb.Message.initPivotAndExtensionObject_(msg, suggestedPivot);
msg.convertedFloatingPointFields_ = {};
if (repeatedFields) {
@@ -364,6 +363,7 @@ jspb.Message.initialize = function(
jspb.Message.EMPTY_LIST_SENTINEL_ :
[]);
} else {
+ jspb.Message.maybeInitEmptyExtensionObject_(msg);
msg.extensionObject_[fieldNumber] =
msg.extensionObject_[fieldNumber] ||
(jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS ?
@@ -408,17 +408,16 @@ jspb.Message.isArray_ = function(o) {
/**
- * Ensures that the array contains an extension object if necessary.
* If the array contains an extension object in its last position, then the
- * object is kept in place and its position is used as the pivot. If not, then
- * create an extension object using suggestedPivot. If suggestedPivot is -1,
- * we don't have an extension object at all, in which case all fields are stored
- * in the array.
+ * object is kept in place and its position is used as the pivot. If not,
+ * decides the pivot of the message based on suggestedPivot without
+ * materializing the extension object.
+ *
* @param {!jspb.Message} msg The JsPb proto to modify.
* @param {number} suggestedPivot See description for initialize().
* @private
*/
-jspb.Message.materializeExtensionObject_ = function(msg, suggestedPivot) {
+jspb.Message.initPivotAndExtensionObject_ = function(msg, suggestedPivot) {
if (msg.array.length) {
var foundIndex = msg.array.length - 1;
var obj = msg.array[foundIndex];
@@ -434,26 +433,17 @@ jspb.Message.materializeExtensionObject_ = function(msg, suggestedPivot) {
return;
}
}
- // This complexity exists because we keep all extension fields in the
- // extensionObject_ regardless of proto field number. Changing this would
- // simplify the code here, but it would require changing the serialization
- // format from the server, which is not backwards compatible.
- // TODO(jshneier): Should we just treat extension fields the same as
- // non-extension fields, and select whether they appear in the object or in
- // the array purely based on tag number? This would allow simplifying all the
- // get/setExtension logic, but it would require the breaking change described
- // above.
+
if (suggestedPivot > -1) {
msg.pivot_ = suggestedPivot;
- var pivotIndex = jspb.Message.getIndex_(msg, suggestedPivot);
- if (!jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS) {
- msg.extensionObject_ = msg.array[pivotIndex] = {};
- } else {
- // Initialize to null to avoid changing the shape of the proto when it
- // gets eventually set.
- msg.extensionObject_ = null;
- }
+ // Avoid changing the shape of the proto with an empty extension object by
+ // deferring the materialization of the extension object until the first
+ // time a field set into it (may be due to getting a repeated proto field
+ // from it, in which case a new empty array is set into it at first).
+ msg.extensionObject_ = null;
} else {
+ // suggestedPivot is -1, which means that we don't have an extension object
+ // at all, in which case all fields are stored in the array.
msg.pivot_ = Number.MAX_VALUE;
}
};
@@ -513,7 +503,7 @@ jspb.Message.toObjectExtension = function(proto, obj, extensions,
for (var fieldNumber in extensions) {
var fieldInfo = extensions[fieldNumber];
var value = getExtensionFn.call(proto, fieldInfo);
- if (goog.isDefAndNotNull(value)) {
+ if (value != null) {
for (var name in fieldInfo.fieldName) {
if (fieldInfo.fieldName.hasOwnProperty(name)) {
break; // the compiled field name
@@ -557,7 +547,7 @@ jspb.Message.serializeBinaryExtensions = function(proto, writer, extensions,
'without binary serialization support');
}
var value = getExtensionFn.call(proto, fieldInfo);
- if (goog.isDefAndNotNull(value)) {
+ if (value != null) {
if (fieldInfo.isMessageType()) {
// If the message type of the extension was generated without binary
// support, there may not be a binary message serializer function, and
@@ -647,6 +637,9 @@ jspb.Message.getField = function(msg, fieldNumber) {
}
return val;
} else {
+ if (!msg.extensionObject_) {
+ return undefined;
+ }
var val = msg.extensionObject_[fieldNumber];
if (val === jspb.Message.EMPTY_LIST_SENTINEL_) {
return msg.extensionObject_[fieldNumber] = [];
@@ -657,6 +650,32 @@ jspb.Message.getField = function(msg, fieldNumber) {
/**
+ * Gets the value of a non-extension repeated field.
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @return {!Array}
+ * The field's value.
+ * @protected
+ */
+jspb.Message.getRepeatedField = function(msg, fieldNumber) {
+ if (fieldNumber < msg.pivot_) {
+ var index = jspb.Message.getIndex_(msg, fieldNumber);
+ var val = msg.array[index];
+ if (val === jspb.Message.EMPTY_LIST_SENTINEL_) {
+ return msg.array[index] = [];
+ }
+ return val;
+ }
+
+ var val = msg.extensionObject_[fieldNumber];
+ if (val === jspb.Message.EMPTY_LIST_SENTINEL_) {
+ return msg.extensionObject_[fieldNumber] = [];
+ }
+ return val;
+};
+
+
+/**
* Gets the value of an optional float or double field.
* @param {!jspb.Message} msg A jspb proto.
* @param {number} fieldNumber The field number.
@@ -678,7 +697,7 @@ jspb.Message.getOptionalFloatingPointField = function(msg, fieldNumber) {
* @protected
*/
jspb.Message.getRepeatedFloatingPointField = function(msg, fieldNumber) {
- var values = jspb.Message.getField(msg, fieldNumber);
+ var values = jspb.Message.getRepeatedField(msg, fieldNumber);
if (!msg.convertedFloatingPointFields_) {
msg.convertedFloatingPointFields_ = {};
}
@@ -864,6 +883,7 @@ jspb.Message.setField = function(msg, fieldNumber, value) {
if (fieldNumber < msg.pivot_) {
msg.array[jspb.Message.getIndex_(msg, fieldNumber)] = value;
} else {
+ jspb.Message.maybeInitEmptyExtensionObject_(msg);
msg.extensionObject_[fieldNumber] = value;
}
};
@@ -878,7 +898,7 @@ jspb.Message.setField = function(msg, fieldNumber, value) {
* @protected
*/
jspb.Message.addToRepeatedField = function(msg, fieldNumber, value, opt_index) {
- var arr = jspb.Message.getField(msg, fieldNumber);
+ var arr = jspb.Message.getRepeatedField(msg, fieldNumber);
if (opt_index != undefined) {
arr.splice(opt_index, 0, value);
} else {
@@ -1006,7 +1026,7 @@ jspb.Message.wrapRepeatedField_ = function(msg, ctor, fieldNumber) {
msg.wrappers_ = {};
}
if (!msg.wrappers_[fieldNumber]) {
- var data = jspb.Message.getField(msg, fieldNumber);
+ var data = jspb.Message.getRepeatedField(msg, fieldNumber);
for (var wrappers = [], i = 0; i < data.length; i++) {
wrappers[i] = new ctor(data[i]);
}
@@ -1101,7 +1121,7 @@ jspb.Message.addToRepeatedWrapperField = function(
wrapperArray = msg.wrappers_[fieldNumber] = [];
}
var insertedValue = value ? value : new ctor();
- var array = jspb.Message.getField(msg, fieldNumber);
+ var array = jspb.Message.getRepeatedField(msg, fieldNumber);
if (index != undefined) {
wrapperArray.splice(index, 0, insertedValue);
array.splice(index, 0, insertedValue.toArray());
diff --git a/js/message_test.js b/js/message_test.js
index dc0ae211..dd3d9267 100644
--- a/js/message_test.js
+++ b/js/message_test.js
@@ -33,6 +33,7 @@
goog.setTestOnly();
goog.require('goog.json');
+goog.require('goog.string');
goog.require('goog.testing.asserts');
goog.require('goog.userAgent');
@@ -64,11 +65,13 @@ goog.require('proto.jspb.test.floatingStrField');
goog.require('proto.jspb.test.HasExtensions');
goog.require('proto.jspb.test.IndirectExtension');
goog.require('proto.jspb.test.IsExtension');
+goog.require('proto.jspb.test.MessageWithLargeFieldTags');
goog.require('proto.jspb.test.OptionalFields');
goog.require('proto.jspb.test.OuterEnum');
goog.require('proto.jspb.test.OuterMessage.Complex');
goog.require('proto.jspb.test.Simple1');
goog.require('proto.jspb.test.Simple2');
+goog.require('proto.jspb.test.SingularsWithLargeFieldTags');
goog.require('proto.jspb.test.SpecialCases');
goog.require('proto.jspb.test.TestClone');
goog.require('proto.jspb.test.TestEndsWithBytes');
@@ -83,8 +86,6 @@ goog.require('proto.jspb.test.ExtensionMessage');
goog.require('proto.jspb.test.TestExtensionsMessage');
-
-
describe('Message test suite', function() {
it('testEmptyProto', function() {
var empty1 = new proto.jspb.test.Empty([]);
@@ -273,12 +274,6 @@ describe('Message test suite', function() {
assertFalse(response.hasEnumField());
});
- it('testMessageRegistration', /** @suppress {visibility} */ function() {
- // goog.require(SomeResponse) will include its library, which will in
- // turn add SomeResponse to the message registry.
- assertEquals(jspb.Message.registry_['res'], proto.jspb.test.SomeResponse);
- });
-
it('testClearFields', function() {
var data = ['str', true, [11], [[22], [33]], ['s1', 's2']];
var foo = new proto.jspb.test.OptionalFields(data);
@@ -661,12 +656,7 @@ describe('Message test suite', function() {
it('testInitialization_emptyArray', function() {
var msg = new proto.jspb.test.HasExtensions([]);
- if (jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS) {
- assertArrayEquals([], msg.toArray());
- } else {
- // Extension object is created past all regular fields.
- assertArrayEquals([,,, {}], msg.toArray());
- }
+ assertArrayEquals([], msg.toArray());
});
it('testInitialization_justExtensionObject', function() {
diff --git a/js/proto3_test.proto b/js/proto3_test.proto
index acb67164..0d073ea0 100644
--- a/js/proto3_test.proto
+++ b/js/proto3_test.proto
@@ -86,4 +86,5 @@ enum Proto3Enum {
PROTO3_FOO = 0;
PROTO3_BAR = 1;
PROTO3_BAZ = 2;
+ MSG_PROTO3_BAH = 3;
}
diff --git a/js/test.proto b/js/test.proto
index 2be5b8c1..7c881c0d 100644
--- a/js/test.proto
+++ b/js/test.proto
@@ -235,6 +235,13 @@ message TestEndsWithBytes {
}
+message Int64Types {
+ optional int64 int64_normal = 1 [jstype=JS_NORMAL];
+ optional sint64 int64_string = 2 [jstype=JS_STRING];
+ optional uint64 int64_number = 3 [jstype=JS_NUMBER];
+
+}
+
message TestMapFieldsNoBinary {
map<string, string> map_string_string = 1;
@@ -271,3 +278,4 @@ message Deeply {
}
}
}
+