diff options
Diffstat (limited to 'third_party/protobuf/3.6.0/js')
95 files changed, 27034 insertions, 0 deletions
diff --git a/third_party/protobuf/3.6.0/js/README.md b/third_party/protobuf/3.6.0/js/README.md new file mode 100644 index 0000000000..ef0d4b198a --- /dev/null +++ b/third_party/protobuf/3.6.0/js/README.md @@ -0,0 +1,166 @@ +Protocol Buffers - Google's data interchange format +=================================================== + +[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) + +Copyright 2008 Google Inc. + +This directory contains the JavaScript Protocol Buffers runtime library. + +The library is currently compatible with: + +1. CommonJS-style imports (eg. `var protos = require('my-protos');`) +2. Closure-style imports (eg. `goog.require('my.package.MyProto');`) + +Support for ES6-style imports is not implemented yet. Browsers can +be supported by using Browserify, webpack, Closure Compiler, etc. to +resolve imports at compile time. + +To use Protocol Buffers with JavaScript, you need two main components: + +1. The protobuf runtime library. You can install this with + `npm install google-protobuf`, or use the files in this directory. + If npm is not being used, as of 3.3.0, the files needed are located in binary subdirectory; + arith.js, constants.js, decoder.js, encoder.js, map.js, message.js, reader.js, utils.js, writer.js +2. The Protocol Compiler `protoc`. This translates `.proto` files + into `.js` files. The compiler is not currently available via + npm, but you can download a pre-built binary + [on GitHub](https://github.com/google/protobuf/releases) + (look for the `protoc-*.zip` files under **Downloads**). + + +Setup +===== + +First, obtain the Protocol Compiler. The easiest way is to download +a pre-built binary from [https://github.com/google/protobuf/releases](https://github.com/google/protobuf/releases). + +If you want, you can compile `protoc` from source instead. To do this +follow the instructions in [the top-level +README](https://github.com/google/protobuf/blob/master/src/README.md). + +Once you have `protoc` compiled, you can run the tests by typing: + + $ cd js + $ npm install + $ npm test + + # If your protoc is somewhere else than ../src/protoc, instead do this. + # But make sure your protoc is the same version as this (or compatible)! + $ PROTOC=/usr/local/bin/protoc npm test + +This will run two separate copies of the tests: one that uses +Closure Compiler style imports and one that uses CommonJS imports. +You can see all the CommonJS files in `commonjs_out/`. +If all of these tests pass, you know you have a working setup. + + +Using Protocol Buffers in your own project +========================================== + +To use Protocol Buffers in your own project, you need to integrate +the Protocol Compiler into your build system. The details are a +little different depending on whether you are using Closure imports +or CommonJS imports: + +Closure Imports +--------------- + +If you want to use Closure imports, your build should run a command +like this: + + $ protoc --js_out=library=myproto_libs,binary:. messages.proto base.proto + +For Closure imports, `protoc` will generate a single output file +(`myproto_libs.js` in this example). The generated file will `goog.provide()` +all of the types defined in your .proto files. For example, for the unit +tests the generated files contain many `goog.provide` statements like: + + goog.provide('proto.google.protobuf.DescriptorProto'); + goog.provide('proto.google.protobuf.DescriptorProto.ExtensionRange'); + goog.provide('proto.google.protobuf.DescriptorProto.ReservedRange'); + goog.provide('proto.google.protobuf.EnumDescriptorProto'); + goog.provide('proto.google.protobuf.EnumOptions'); + +The generated code will also `goog.require()` many types in the core library, +and they will require many types in the Google Closure library. So make sure +that your `goog.provide()` / `goog.require()` setup can find all of your +generated code, the core library `.js` files in this directory, and the +Google Closure library itself. + +Once you've done this, you should be able to import your types with +statements like: + + goog.require('proto.my.package.MyMessage'); + + var message = proto.my.package.MyMessage(); + +If unfamiliar with Closure or it's compiler, consider reviewing Closure documentation +https://developers.google.com/closure/library/docs/tutorial +https://developers.google.com/closure/library/docs/closurebuilder +https://developers.google.com/closure/library/docs/depswriter +At a high level, closurebuilder.py can walk dependencies, and compile your code, and all dependencies for Protobuf into a single .js file. Using depsbuilder.py to generate a dependency file can also be considered for non-production dev environments. + +CommonJS imports +---------------- + +If you want to use CommonJS imports, your build should run a command +like this: + + $ protoc --js_out=import_style=commonjs,binary:. messages.proto base.proto + +For CommonJS imports, `protoc` will spit out one file per input file +(so `messages_pb.js` and `base_pb.js` in this example). The generated +code will depend on the core runtime, which should be in a file called +`google-protobuf.js`. If you are installing from `npm`, this file should +already be built and available. If you are running from GitHub, you need +to build it first by running: + + $ gulp dist + +Once you've done this, you should be able to import your types with +statements like: + + var messages = require('./messages_pb'); + + var message = new messages.MyMessage(); + +The `--js_out` flag +------------------- + +The syntax of the `--js_out` flag is: + + --js_out=[OPTIONS:]output_dir + +Where `OPTIONS` are separated by commas. Options are either `opt=val` or +just `opt` (for options that don't take a value). The available options +are specified and documented in the `GeneratorOptions` struct in +[src/google/protobuf/compiler/js/js_generator.h](https://github.com/google/protobuf/blob/master/src/google/protobuf/compiler/js/js_generator.h#L53). + +Some examples: + +- `--js_out=library=myprotos_lib.js,binary:.`: this contains the options + `library=myprotos.lib.js` and `binary` and outputs to the current directory. + The `import_style` option is left to the default, which is `closure`. +- `--js_out=import_style=commonjs,binary:protos`: this contains the options + `import_style=commonjs` and `binary` and outputs to the directory `protos`. + +API +=== + +The API is not well-documented yet. Here is a quick example to give you an +idea of how the library generally works: + + var message = new MyMessage(); + + message.setName("John Doe"); + message.setAge(25); + message.setPhoneNumbers(["800-555-1212", "800-555-0000"]); + + // Serializes to a UInt8Array. + var bytes = message.serializeBinary(); + + var message2 = MyMessage.deserializeBinary(bytes); + +For more examples, see the tests. You can also look at the generated code +to see what methods are defined for your generated messages. diff --git a/third_party/protobuf/3.6.0/js/binary/arith.js b/third_party/protobuf/3.6.0/js/binary/arith.js new file mode 100644 index 0000000000..62528a263a --- /dev/null +++ b/third_party/protobuf/3.6.0/js/binary/arith.js @@ -0,0 +1,413 @@ +// 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 This file contains helper code used by jspb.utils to + * handle 64-bit integer conversion to/from strings. + * + * @author cfallin@google.com (Chris Fallin) + * + * TODO(haberman): move this to javascript/closure/math? + */ + +goog.provide('jspb.arith.Int64'); +goog.provide('jspb.arith.UInt64'); + +/** + * UInt64 implements some 64-bit arithmetic routines necessary for properly + * handling 64-bit integer fields. It implements lossless integer arithmetic on + * top of JavaScript's number type, which has only 53 bits of precision, by + * representing 64-bit integers as two 32-bit halves. + * + * @param {number} lo The low 32 bits. + * @param {number} hi The high 32 bits. + * @constructor + */ +jspb.arith.UInt64 = function(lo, hi) { + /** + * The low 32 bits. + * @public {number} + */ + this.lo = lo; + /** + * The high 32 bits. + * @public {number} + */ + this.hi = hi; +}; + + +/** + * Compare two 64-bit numbers. Returns -1 if the first is + * less, +1 if the first is greater, or 0 if both are equal. + * @param {!jspb.arith.UInt64} other + * @return {number} + */ +jspb.arith.UInt64.prototype.cmp = function(other) { + if (this.hi < other.hi || (this.hi == other.hi && this.lo < other.lo)) { + return -1; + } else if (this.hi == other.hi && this.lo == other.lo) { + return 0; + } else { + return 1; + } +}; + + +/** + * Right-shift this number by one bit. + * @return {!jspb.arith.UInt64} + */ +jspb.arith.UInt64.prototype.rightShift = function() { + var hi = this.hi >>> 1; + var lo = (this.lo >>> 1) | ((this.hi & 1) << 31); + return new jspb.arith.UInt64(lo >>> 0, hi >>> 0); +}; + + +/** + * Left-shift this number by one bit. + * @return {!jspb.arith.UInt64} + */ +jspb.arith.UInt64.prototype.leftShift = function() { + var lo = this.lo << 1; + var hi = (this.hi << 1) | (this.lo >>> 31); + return new jspb.arith.UInt64(lo >>> 0, hi >>> 0); +}; + + +/** + * Test the MSB. + * @return {boolean} + */ +jspb.arith.UInt64.prototype.msb = function() { + return !!(this.hi & 0x80000000); +}; + + +/** + * Test the LSB. + * @return {boolean} + */ +jspb.arith.UInt64.prototype.lsb = function() { + return !!(this.lo & 1); +}; + + +/** + * Test whether this number is zero. + * @return {boolean} + */ +jspb.arith.UInt64.prototype.zero = function() { + return this.lo == 0 && this.hi == 0; +}; + + +/** + * Add two 64-bit numbers to produce a 64-bit number. + * @param {!jspb.arith.UInt64} other + * @return {!jspb.arith.UInt64} + */ +jspb.arith.UInt64.prototype.add = function(other) { + var lo = ((this.lo + other.lo) & 0xffffffff) >>> 0; + var hi = + (((this.hi + other.hi) & 0xffffffff) >>> 0) + + (((this.lo + other.lo) >= 0x100000000) ? 1 : 0); + return new jspb.arith.UInt64(lo >>> 0, hi >>> 0); +}; + + +/** + * Subtract two 64-bit numbers to produce a 64-bit number. + * @param {!jspb.arith.UInt64} other + * @return {!jspb.arith.UInt64} + */ +jspb.arith.UInt64.prototype.sub = function(other) { + var lo = ((this.lo - other.lo) & 0xffffffff) >>> 0; + var hi = + (((this.hi - other.hi) & 0xffffffff) >>> 0) - + (((this.lo - other.lo) < 0) ? 1 : 0); + return new jspb.arith.UInt64(lo >>> 0, hi >>> 0); +}; + + +/** + * Multiply two 32-bit numbers to produce a 64-bit number. + * @param {number} a The first integer: must be in [0, 2^32-1). + * @param {number} b The second integer: must be in [0, 2^32-1). + * @return {!jspb.arith.UInt64} + */ +jspb.arith.UInt64.mul32x32 = function(a, b) { + // Directly multiplying two 32-bit numbers may produce up to 64 bits of + // precision, thus losing precision because of the 53-bit mantissa of + // JavaScript numbers. So we multiply with 16-bit digits (radix 65536) + // instead. + var aLow = (a & 0xffff); + var aHigh = (a >>> 16); + var bLow = (b & 0xffff); + var bHigh = (b >>> 16); + var productLow = + // 32-bit result, result bits 0-31, take all 32 bits + (aLow * bLow) + + // 32-bit result, result bits 16-47, take bottom 16 as our top 16 + ((aLow * bHigh) & 0xffff) * 0x10000 + + // 32-bit result, result bits 16-47, take bottom 16 as our top 16 + ((aHigh * bLow) & 0xffff) * 0x10000; + var productHigh = + // 32-bit result, result bits 32-63, take all 32 bits + (aHigh * bHigh) + + // 32-bit result, result bits 16-47, take top 16 as our bottom 16 + ((aLow * bHigh) >>> 16) + + // 32-bit result, result bits 16-47, take top 16 as our bottom 16 + ((aHigh * bLow) >>> 16); + + // Carry. Note that we actually have up to *two* carries due to addition of + // three terms. + while (productLow >= 0x100000000) { + productLow -= 0x100000000; + productHigh += 1; + } + + return new jspb.arith.UInt64(productLow >>> 0, productHigh >>> 0); +}; + + +/** + * Multiply this number by a 32-bit number, producing a 96-bit number, then + * truncate the top 32 bits. + * @param {number} a The multiplier. + * @return {!jspb.arith.UInt64} + */ +jspb.arith.UInt64.prototype.mul = function(a) { + // Produce two parts: at bits 0-63, and 32-95. + var lo = jspb.arith.UInt64.mul32x32(this.lo, a); + var hi = jspb.arith.UInt64.mul32x32(this.hi, a); + // Left-shift hi by 32 bits, truncating its top bits. The parts will then be + // aligned for addition. + hi.hi = hi.lo; + hi.lo = 0; + return lo.add(hi); +}; + + +/** + * Divide a 64-bit number by a 32-bit number to produce a + * 64-bit quotient and a 32-bit remainder. + * @param {number} _divisor + * @return {Array<jspb.arith.UInt64>} array of [quotient, remainder], + * unless divisor is 0, in which case an empty array is returned. + */ +jspb.arith.UInt64.prototype.div = function(_divisor) { + if (_divisor == 0) { + return []; + } + + // We perform long division using a radix-2 algorithm, for simplicity (i.e., + // one bit at a time). TODO: optimize to a radix-2^32 algorithm, taking care + // to get the variable shifts right. + var quotient = new jspb.arith.UInt64(0, 0); + var remainder = new jspb.arith.UInt64(this.lo, this.hi); + var divisor = new jspb.arith.UInt64(_divisor, 0); + var unit = new jspb.arith.UInt64(1, 0); + + // Left-shift the divisor and unit until the high bit of divisor is set. + while (!divisor.msb()) { + divisor = divisor.leftShift(); + unit = unit.leftShift(); + } + + // Perform long division one bit at a time. + while (!unit.zero()) { + // If divisor < remainder, add unit to quotient and subtract divisor from + // remainder. + if (divisor.cmp(remainder) <= 0) { + quotient = quotient.add(unit); + remainder = remainder.sub(divisor); + } + // Right-shift the divisor and unit. + divisor = divisor.rightShift(); + unit = unit.rightShift(); + } + + return [quotient, remainder]; +}; + + +/** + * Convert a 64-bit number to a string. + * @return {string} + * @override + */ +jspb.arith.UInt64.prototype.toString = function() { + var result = ''; + var num = this; + while (!num.zero()) { + var divResult = num.div(10); + var quotient = divResult[0], remainder = divResult[1]; + result = remainder.lo + result; + num = quotient; + } + if (result == '') { + result = '0'; + } + return result; +}; + + +/** + * Parse a string into a 64-bit number. Returns `null` on a parse error. + * @param {string} s + * @return {?jspb.arith.UInt64} + */ +jspb.arith.UInt64.fromString = function(s) { + var result = new jspb.arith.UInt64(0, 0); + // optimization: reuse this instance for each digit. + var digit64 = new jspb.arith.UInt64(0, 0); + for (var i = 0; i < s.length; i++) { + if (s[i] < '0' || s[i] > '9') { + return null; + } + var digit = parseInt(s[i], 10); + digit64.lo = digit; + result = result.mul(10).add(digit64); + } + return result; +}; + + +/** + * Make a copy of the uint64. + * @return {!jspb.arith.UInt64} + */ +jspb.arith.UInt64.prototype.clone = function() { + return new jspb.arith.UInt64(this.lo, this.hi); +}; + + +/** + * Int64 is like UInt64, but modifies string conversions to interpret the stored + * 64-bit value as a twos-complement-signed integer. It does *not* support the + * full range of operations that UInt64 does: only add, subtract, and string + * conversions. + * + * N.B. that multiply and divide routines are *NOT* supported. They will throw + * exceptions. (They are not necessary to implement string conversions, which + * are the only operations we really need in jspb.) + * + * @param {number} lo The low 32 bits. + * @param {number} hi The high 32 bits. + * @constructor + */ +jspb.arith.Int64 = function(lo, hi) { + /** + * The low 32 bits. + * @public {number} + */ + this.lo = lo; + /** + * The high 32 bits. + * @public {number} + */ + this.hi = hi; +}; + + +/** + * Add two 64-bit numbers to produce a 64-bit number. + * @param {!jspb.arith.Int64} other + * @return {!jspb.arith.Int64} + */ +jspb.arith.Int64.prototype.add = function(other) { + var lo = ((this.lo + other.lo) & 0xffffffff) >>> 0; + var hi = + (((this.hi + other.hi) & 0xffffffff) >>> 0) + + (((this.lo + other.lo) >= 0x100000000) ? 1 : 0); + return new jspb.arith.Int64(lo >>> 0, hi >>> 0); +}; + + +/** + * Subtract two 64-bit numbers to produce a 64-bit number. + * @param {!jspb.arith.Int64} other + * @return {!jspb.arith.Int64} + */ +jspb.arith.Int64.prototype.sub = function(other) { + var lo = ((this.lo - other.lo) & 0xffffffff) >>> 0; + var hi = + (((this.hi - other.hi) & 0xffffffff) >>> 0) - + (((this.lo - other.lo) < 0) ? 1 : 0); + return new jspb.arith.Int64(lo >>> 0, hi >>> 0); +}; + + +/** + * Make a copy of the int64. + * @return {!jspb.arith.Int64} + */ +jspb.arith.Int64.prototype.clone = function() { + return new jspb.arith.Int64(this.lo, this.hi); +}; + + +/** + * Convert a 64-bit number to a string. + * @return {string} + * @override + */ +jspb.arith.Int64.prototype.toString = function() { + // If the number is negative, find its twos-complement inverse. + var sign = (this.hi & 0x80000000) != 0; + var num = new jspb.arith.UInt64(this.lo, this.hi); + if (sign) { + num = new jspb.arith.UInt64(0, 0).sub(num); + } + return (sign ? '-' : '') + num.toString(); +}; + + +/** + * Parse a string into a 64-bit number. Returns `null` on a parse error. + * @param {string} s + * @return {?jspb.arith.Int64} + */ +jspb.arith.Int64.fromString = function(s) { + var hasNegative = (s.length > 0 && s[0] == '-'); + if (hasNegative) { + s = s.substring(1); + } + var num = jspb.arith.UInt64.fromString(s); + if (num === null) { + return null; + } + if (hasNegative) { + num = new jspb.arith.UInt64(0, 0).sub(num); + } + return new jspb.arith.Int64(num.lo, num.hi); +}; diff --git a/third_party/protobuf/3.6.0/js/binary/arith_test.js b/third_party/protobuf/3.6.0/js/binary/arith_test.js new file mode 100644 index 0000000000..dd5791a7bb --- /dev/null +++ b/third_party/protobuf/3.6.0/js/binary/arith_test.js @@ -0,0 +1,354 @@ +// 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('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); + expect(a.cmp(b)).toEqual(0); + expect(b.cmp(a)).toEqual(0); + b.lo -= 1; + expect(a.cmp(b)).toEqual(1); + expect(b.cmp(a)).toEqual(-1); + b.lo += 2; + expect(a.cmp(b)).toEqual(-1); + expect(b.cmp(a)).toEqual(1); + b.lo = a.lo; + b.hi = a.hi - 1; + expect(a.cmp(b)).toEqual(1); + expect(b.cmp(a)).toEqual(-1); + + expect(a.zero()).toEqual(false); + expect(a.msb()).toEqual(false); + expect(a.lsb()).toEqual(false); + a.hi = 0; + a.lo = 0; + expect(a.zero()).toEqual(true); + a.hi = 0x80000000; + expect(a.zero()).toEqual(false); + expect(a.msb()).toEqual(true); + a.lo = 0x00000001; + expect(a.lsb()).toEqual(true); + }); + + + /** + * Tests shifts. + */ + it('testShifts', function() { + var a = new jspb.arith.UInt64(1, 0); + expect(a.lo).toEqual(1); + expect(a.hi).toEqual(0); + var orig = a; + a = a.leftShift(); + expect(orig.lo).toEqual(1); // original unmodified. + expect(orig.hi).toEqual(0); + expect(a.lo).toEqual(2); + expect(a.hi).toEqual(0); + a = a.leftShift(); + expect(a.lo).toEqual(4); + expect(a.hi).toEqual(0); + for (var i = 0; i < 29; i++) { + a = a.leftShift(); + } + expect(a.lo).toEqual(0x80000000); + expect(a.hi).toEqual(0); + a = a.leftShift(); + expect(a.lo).toEqual(0); + expect(a.hi).toEqual(1); + a = a.leftShift(); + expect(a.lo).toEqual(0); + expect(a.hi).toEqual(2); + a = a.rightShift(); + a = a.rightShift(); + expect(a.lo).toEqual(0x80000000); + expect(a.hi).toEqual(0); + a = a.rightShift(); + expect(a.lo).toEqual(0x40000000); + expect(a.hi).toEqual(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); + expect(a.lo).toEqual(0x89abcdef); // originals unmodified. + expect(a.hi).toEqual(0x01234567); + expect(b.lo).toEqual(0xff52ab91); + expect(b.hi).toEqual(0x92fa2123); + expect(c.lo).toEqual(0x88fe7980); + expect(c.hi).toEqual(0x941d668b); + + // Simple addition without carry. + a.lo = 2; + a.hi = 0; + b.lo = 3; + b.hi = 0; + c = a.add(b); + expect(c.lo).toEqual(5); + expect(c.hi).toEqual(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); + expect(c.hi).toEqual(a.hi); + expect(c.lo).toEqual(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); + expect(c.lo).toEqual(cLow); + expect(c.hi).toEqual(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]); + expect(prod.lo).toEqual(testData[i][3]); + expect(prod.hi).toEqual(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]; + expect(quotient.lo).toEqual(testData[i][3]); + expect(quotient.hi).toEqual(testData[i][4]); + expect(remainder.lo).toEqual(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()); + expect(roundtrip.lo).toEqual(a.lo); + expect(roundtrip.hi).toEqual(a.hi); + expect(a.toString()).toEqual(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(); + expect(roundtrip).toEqual(testStrings[i]); + } + }); +}); diff --git a/third_party/protobuf/3.6.0/js/binary/constants.js b/third_party/protobuf/3.6.0/js/binary/constants.js new file mode 100644 index 0000000000..21c5889c93 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/binary/constants.js @@ -0,0 +1,376 @@ +// 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 This file contains constants and typedefs used by + * jspb.BinaryReader and BinaryWriter. + * + * @author aappleby@google.com (Austin Appleby) + */ + +goog.provide('jspb.AnyFieldType'); +goog.provide('jspb.BinaryConstants'); +goog.provide('jspb.BinaryMessage'); +goog.provide('jspb.BuilderFunction'); +goog.provide('jspb.ByteSource'); +goog.provide('jspb.ClonerFunction'); +goog.provide('jspb.ComparerFunction'); +goog.provide('jspb.ConstBinaryMessage'); +goog.provide('jspb.PrunerFunction'); +goog.provide('jspb.ReaderFunction'); +goog.provide('jspb.RecyclerFunction'); +goog.provide('jspb.RepeatedFieldType'); +goog.provide('jspb.ScalarFieldType'); +goog.provide('jspb.WriterFunction'); + + +goog.forwardDeclare('jspb.BinaryMessage'); +goog.forwardDeclare('jspb.BinaryReader'); +goog.forwardDeclare('jspb.BinaryWriter'); +goog.forwardDeclare('jspb.Message'); +goog.forwardDeclare('jsproto.BinaryExtension'); + + + +/** + * Base interface class for all const messages. + * @interface + */ +jspb.ConstBinaryMessage = function() {}; + +/** + * Generate a debug string for this proto that is in proto2 text format. + * @return {string} The debug string. + */ +jspb.ConstBinaryMessage.prototype.toDebugString; + +/** + * Helper to generate a debug string for this proto at some indent level. The + * first line is not indented. + * @param {number} indentLevel The number of spaces by which to indent lines. + * @return {string} The debug string. + * @protected + */ +jspb.ConstBinaryMessage.prototype.toDebugStringInternal; + +/** + * Base interface class for all messages. Does __not__ define any methods, as + * doing so on a widely-used interface defeats dead-code elimination. + * @interface + * @extends {jspb.ConstBinaryMessage} + */ +jspb.BinaryMessage = function() {}; + + +/** + * The types convertible to Uint8Arrays. Strings are assumed to be + * base64-encoded. + * @typedef {ArrayBuffer|Uint8Array|Array<number>|string} + */ +jspb.ByteSource; + + +/** + * A scalar field in jspb can be a boolean, number, or string. + * @typedef {boolean|number|string} + */ +jspb.ScalarFieldType; + + +/** + * A repeated field in jspb is an array of scalars, blobs, or messages. + * @typedef {!Array<jspb.ScalarFieldType>| + !Array<!Uint8Array>| + !Array<!jspb.ConstBinaryMessage>| + !Array<!jspb.BinaryMessage>} + */ +jspb.RepeatedFieldType; + + +/** + * A field in jspb can be a scalar, a block of bytes, another proto, or an + * array of any of the above. + * @typedef {jspb.ScalarFieldType| + jspb.RepeatedFieldType| + !Uint8Array| + !jspb.ConstBinaryMessage| + !jspb.BinaryMessage| + !jsproto.BinaryExtension} + */ +jspb.AnyFieldType; + + +/** + * A builder function creates an instance of a message object. + * @typedef {function():!jspb.BinaryMessage} + */ +jspb.BuilderFunction; + + +/** + * A cloner function creates a deep copy of a message object. + * @typedef {function(jspb.ConstBinaryMessage):jspb.BinaryMessage} + */ +jspb.ClonerFunction; + + +/** + * A recycler function destroys an instance of a message object. + * @typedef {function(!jspb.BinaryMessage):void} + */ +jspb.RecyclerFunction; + + +/** + * A reader function initializes a message using data from a BinaryReader. + * @typedef {function(!jspb.BinaryMessage, !jspb.BinaryReader):void} + */ +jspb.ReaderFunction; + + +/** + * A writer function serializes a message to a BinaryWriter. + * @typedef {function((!jspb.Message|!jspb.ConstBinaryMessage), + * !jspb.BinaryWriter):void} + */ +jspb.WriterFunction; + + +/** + * A pruner function removes default-valued fields and empty submessages from a + * message and returns either the pruned message or null if the entire message + * was pruned away. + * @typedef {function(?jspb.BinaryMessage):?jspb.BinaryMessage} + */ +jspb.PrunerFunction; + + +/** + * A comparer function returns true if two protos are equal. + * @typedef {!function(?jspb.ConstBinaryMessage, + * ?jspb.ConstBinaryMessage):boolean} + */ +jspb.ComparerFunction; + + +/** + * Field type codes, taken from proto2/public/wire_format_lite.h. + * @enum {number} + */ +jspb.BinaryConstants.FieldType = { + INVALID: -1, + DOUBLE: 1, + FLOAT: 2, + INT64: 3, + UINT64: 4, + INT32: 5, + FIXED64: 6, + FIXED32: 7, + BOOL: 8, + STRING: 9, + GROUP: 10, + MESSAGE: 11, + BYTES: 12, + UINT32: 13, + ENUM: 14, + SFIXED32: 15, + SFIXED64: 16, + SINT32: 17, + SINT64: 18, + + // Extended types for Javascript + + FHASH64: 30, // 64-bit hash string, fixed-length encoding. + VHASH64: 31 // 64-bit hash string, varint encoding. +}; + + +/** + * Wire-format type codes, taken from proto2/public/wire_format_lite.h. + * @enum {number} + */ +jspb.BinaryConstants.WireType = { + INVALID: -1, + VARINT: 0, + FIXED64: 1, + DELIMITED: 2, + START_GROUP: 3, + END_GROUP: 4, + FIXED32: 5 +}; + + +/** + * Translates field type to wire type. + * @param {jspb.BinaryConstants.FieldType} fieldType + * @return {jspb.BinaryConstants.WireType} + */ +jspb.BinaryConstants.FieldTypeToWireType = function(fieldType) { + var fieldTypes = jspb.BinaryConstants.FieldType; + var wireTypes = jspb.BinaryConstants.WireType; + switch (fieldType) { + case fieldTypes.INT32: + case fieldTypes.INT64: + case fieldTypes.UINT32: + case fieldTypes.UINT64: + case fieldTypes.SINT32: + case fieldTypes.SINT64: + case fieldTypes.BOOL: + case fieldTypes.ENUM: + case fieldTypes.VHASH64: + return wireTypes.VARINT; + + case fieldTypes.DOUBLE: + case fieldTypes.FIXED64: + case fieldTypes.SFIXED64: + case fieldTypes.FHASH64: + return wireTypes.FIXED64; + + case fieldTypes.STRING: + case fieldTypes.MESSAGE: + case fieldTypes.BYTES: + return wireTypes.DELIMITED; + + case fieldTypes.FLOAT: + case fieldTypes.FIXED32: + case fieldTypes.SFIXED32: + return wireTypes.FIXED32; + + case fieldTypes.INVALID: + case fieldTypes.GROUP: + default: + return wireTypes.INVALID; + } +}; + + +/** + * Flag to indicate a missing field. + * @const {number} + */ +jspb.BinaryConstants.INVALID_FIELD_NUMBER = -1; + + +/** + * The smallest denormal float32 value. + * @const {number} + */ +jspb.BinaryConstants.FLOAT32_EPS = 1.401298464324817e-45; + + +/** + * The smallest normal float64 value. + * @const {number} + */ +jspb.BinaryConstants.FLOAT32_MIN = 1.1754943508222875e-38; + + +/** + * The largest finite float32 value. + * @const {number} + */ +jspb.BinaryConstants.FLOAT32_MAX = 3.4028234663852886e+38; + + +/** + * The smallest denormal float64 value. + * @const {number} + */ +jspb.BinaryConstants.FLOAT64_EPS = 5e-324; + + +/** + * The smallest normal float64 value. + * @const {number} + */ +jspb.BinaryConstants.FLOAT64_MIN = 2.2250738585072014e-308; + + +/** + * The largest finite float64 value. + * @const {number} + */ +jspb.BinaryConstants.FLOAT64_MAX = 1.7976931348623157e+308; + + +/** + * Convenience constant equal to 2^20. + * @const {number} + */ +jspb.BinaryConstants.TWO_TO_20 = 1048576; + + +/** + * Convenience constant equal to 2^23. + * @const {number} + */ +jspb.BinaryConstants.TWO_TO_23 = 8388608; + + +/** + * Convenience constant equal to 2^31. + * @const {number} + */ +jspb.BinaryConstants.TWO_TO_31 = 2147483648; + + +/** + * Convenience constant equal to 2^32. + * @const {number} + */ +jspb.BinaryConstants.TWO_TO_32 = 4294967296; + + +/** + * Convenience constant equal to 2^52. + * @const {number} + */ +jspb.BinaryConstants.TWO_TO_52 = 4503599627370496; + + +/** + * Convenience constant equal to 2^63. + * @const {number} + */ +jspb.BinaryConstants.TWO_TO_63 = 9223372036854775808; + + +/** + * Convenience constant equal to 2^64. + * @const {number} + */ +jspb.BinaryConstants.TWO_TO_64 = 18446744073709551616; + + +/** + * Eight-character string of zeros, used as the default 64-bit hash value. + * @const {string} + */ +jspb.BinaryConstants.ZERO_HASH = '\0\0\0\0\0\0\0\0'; diff --git a/third_party/protobuf/3.6.0/js/binary/decoder.js b/third_party/protobuf/3.6.0/js/binary/decoder.js new file mode 100644 index 0000000000..e33bf1be9c --- /dev/null +++ b/third_party/protobuf/3.6.0/js/binary/decoder.js @@ -0,0 +1,1069 @@ +// 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 This file contains utilities for decoding primitive values + * (signed and unsigned integers, varints, booleans, enums, hashes, strings, + * and raw bytes) embedded in Uint8Arrays into their corresponding Javascript + * types. + * + * Major caveat - Javascript is unable to accurately represent integers larger + * than 2^53 due to its use of a double-precision floating point format or all + * numbers. If you need to guarantee that 64-bit values survive with all bits + * intact, you _must_ read them using one of the Hash64 methods, which return + * an 8-character string. + * + * @author aappleby@google.com (Austin Appleby) + */ + +goog.provide('jspb.BinaryDecoder'); +goog.provide('jspb.BinaryIterator'); + +goog.require('goog.asserts'); +goog.require('goog.crypt'); +goog.require('jspb.utils'); + + + +/** + * Simple helper class for traversing the contents of repeated scalar fields. + * that may or may not have been packed into a wire-format blob. + * @param {?jspb.BinaryDecoder=} opt_decoder + * @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=} + * opt_next The decoder method to use for next(). + * @param {?Array<number|boolean|string>=} opt_elements + * @constructor + * @struct + */ +jspb.BinaryIterator = function(opt_decoder, opt_next, opt_elements) { + /** @private {jspb.BinaryDecoder} */ + this.decoder_ = null; + + /** + * The BinaryDecoder member function used when iterating over packed data. + * @private {?function(this:jspb.BinaryDecoder):(number|boolean|string)} + */ + this.nextMethod_ = null; + + /** @private {?Array<number|boolean|string>} */ + this.elements_ = null; + + /** @private {number} */ + this.cursor_ = 0; + + /** @private {number|boolean|string|null} */ + this.nextValue_ = null; + + /** @private {boolean} */ + this.atEnd_ = true; + + this.init_(opt_decoder, opt_next, opt_elements); +}; + + +/** + * @param {?jspb.BinaryDecoder=} opt_decoder + * @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=} + * opt_next The decoder method to use for next(). + * @param {?Array<number|boolean|string>=} opt_elements + * @private + */ +jspb.BinaryIterator.prototype.init_ = + function(opt_decoder, opt_next, opt_elements) { + if (opt_decoder && opt_next) { + this.decoder_ = opt_decoder; + this.nextMethod_ = opt_next; + } + this.elements_ = opt_elements || null; + this.cursor_ = 0; + this.nextValue_ = null; + this.atEnd_ = !this.decoder_ && !this.elements_; + + this.next(); +}; + + +/** + * Global pool of BinaryIterator instances. + * @private {!Array<!jspb.BinaryIterator>} + */ +jspb.BinaryIterator.instanceCache_ = []; + + +/** + * Allocates a BinaryIterator from the cache, creating a new one if the cache + * is empty. + * @param {?jspb.BinaryDecoder=} opt_decoder + * @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=} + * opt_next The decoder method to use for next(). + * @param {?Array<number|boolean|string>=} opt_elements + * @return {!jspb.BinaryIterator} + */ +jspb.BinaryIterator.alloc = function(opt_decoder, opt_next, opt_elements) { + if (jspb.BinaryIterator.instanceCache_.length) { + var iterator = jspb.BinaryIterator.instanceCache_.pop(); + iterator.init_(opt_decoder, opt_next, opt_elements); + return iterator; + } else { + return new jspb.BinaryIterator(opt_decoder, opt_next, opt_elements); + } +}; + + +/** + * Puts this instance back in the instance cache. + */ +jspb.BinaryIterator.prototype.free = function() { + this.clear(); + if (jspb.BinaryIterator.instanceCache_.length < 100) { + jspb.BinaryIterator.instanceCache_.push(this); + } +}; + + +/** + * Clears the iterator. + */ +jspb.BinaryIterator.prototype.clear = function() { + if (this.decoder_) { + this.decoder_.free(); + } + this.decoder_ = null; + this.nextMethod_ = null; + this.elements_ = null; + this.cursor_ = 0; + this.nextValue_ = null; + this.atEnd_ = true; +}; + + +/** + * Returns the element at the iterator, or null if the iterator is invalid or + * past the end of the decoder/array. + * @return {number|boolean|string|null} + */ +jspb.BinaryIterator.prototype.get = function() { + return this.nextValue_; +}; + + +/** + * Returns true if the iterator is at the end of the decoder/array. + * @return {boolean} + */ +jspb.BinaryIterator.prototype.atEnd = function() { + return this.atEnd_; +}; + + +/** + * Returns the element at the iterator and steps to the next element, + * equivalent to '*pointer++' in C. + * @return {number|boolean|string|null} + */ +jspb.BinaryIterator.prototype.next = function() { + var lastValue = this.nextValue_; + if (this.decoder_) { + if (this.decoder_.atEnd()) { + this.nextValue_ = null; + this.atEnd_ = true; + } else { + this.nextValue_ = this.nextMethod_.call(this.decoder_); + } + } else if (this.elements_) { + if (this.cursor_ == this.elements_.length) { + this.nextValue_ = null; + this.atEnd_ = true; + } else { + this.nextValue_ = this.elements_[this.cursor_++]; + } + } + return lastValue; +}; + + + +/** + * BinaryDecoder implements the decoders for all the wire types specified in + * https://developers.google.com/protocol-buffers/docs/encoding. + * + * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from. + * @param {number=} opt_start The optional offset to start reading at. + * @param {number=} opt_length The optional length of the block to read - + * we'll throw an assertion if we go off the end of the block. + * @constructor + * @struct + */ +jspb.BinaryDecoder = function(opt_bytes, opt_start, opt_length) { + /** + * Typed byte-wise view of the source buffer. + * @private {?Uint8Array} + */ + this.bytes_ = null; + + /** + * Start point of the block to read. + * @private {number} + */ + this.start_ = 0; + + /** + * End point of the block to read. + * @private {number} + */ + this.end_ = 0; + + /** + * Current read location in bytes_. + * @private {number} + */ + this.cursor_ = 0; + + /** + * Temporary storage for the low 32 bits of 64-bit data types that we're + * decoding. + * @private {number} + */ + this.tempLow_ = 0; + + /** + * Temporary storage for the high 32 bits of 64-bit data types that we're + * decoding. + * @private {number} + */ + this.tempHigh_ = 0; + + /** + * Set to true if this decoder encountered an error due to corrupt data. + * @private {boolean} + */ + this.error_ = false; + + if (opt_bytes) { + this.setBlock(opt_bytes, opt_start, opt_length); + } +}; + + +/** + * Global pool of BinaryDecoder instances. + * @private {!Array<!jspb.BinaryDecoder>} + */ +jspb.BinaryDecoder.instanceCache_ = []; + + +/** + * Pops an instance off the instance cache, or creates one if the cache is + * empty. + * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from. + * @param {number=} opt_start The optional offset to start reading at. + * @param {number=} opt_length The optional length of the block to read - + * we'll throw an assertion if we go off the end of the block. + * @return {!jspb.BinaryDecoder} + */ +jspb.BinaryDecoder.alloc = function(opt_bytes, opt_start, opt_length) { + if (jspb.BinaryDecoder.instanceCache_.length) { + var newDecoder = jspb.BinaryDecoder.instanceCache_.pop(); + if (opt_bytes) { + newDecoder.setBlock(opt_bytes, opt_start, opt_length); + } + return newDecoder; + } else { + return new jspb.BinaryDecoder(opt_bytes, opt_start, opt_length); + } +}; + + +/** + * Puts this instance back in the instance cache. + */ +jspb.BinaryDecoder.prototype.free = function() { + this.clear(); + if (jspb.BinaryDecoder.instanceCache_.length < 100) { + jspb.BinaryDecoder.instanceCache_.push(this); + } +}; + + +/** + * Makes a copy of this decoder. + * @return {!jspb.BinaryDecoder} + */ +jspb.BinaryDecoder.prototype.clone = function() { + return jspb.BinaryDecoder.alloc(this.bytes_, + this.start_, this.end_ - this.start_); +}; + + +/** + * Clears the decoder. + */ +jspb.BinaryDecoder.prototype.clear = function() { + this.bytes_ = null; + this.start_ = 0; + this.end_ = 0; + this.cursor_ = 0; + this.error_ = false; +}; + + +/** + * Returns the raw buffer. + * @return {?Uint8Array} The raw buffer. + */ +jspb.BinaryDecoder.prototype.getBuffer = function() { + return this.bytes_; +}; + + +/** + * Changes the block of bytes we're decoding. + * @param {!jspb.ByteSource} data The bytes we're reading from. + * @param {number=} opt_start The optional offset to start reading at. + * @param {number=} opt_length The optional length of the block to read - + * we'll throw an assertion if we go off the end of the block. + */ +jspb.BinaryDecoder.prototype.setBlock = + function(data, opt_start, opt_length) { + this.bytes_ = jspb.utils.byteSourceToUint8Array(data); + this.start_ = goog.isDef(opt_start) ? opt_start : 0; + this.end_ = + goog.isDef(opt_length) ? this.start_ + opt_length : this.bytes_.length; + this.cursor_ = this.start_; +}; + + +/** + * @return {number} + */ +jspb.BinaryDecoder.prototype.getEnd = function() { + return this.end_; +}; + + +/** + * @param {number} end + */ +jspb.BinaryDecoder.prototype.setEnd = function(end) { + this.end_ = end; +}; + + +/** + * Moves the read cursor back to the start of the block. + */ +jspb.BinaryDecoder.prototype.reset = function() { + this.cursor_ = this.start_; +}; + + +/** + * Returns the internal read cursor. + * @return {number} The internal read cursor. + */ +jspb.BinaryDecoder.prototype.getCursor = function() { + return this.cursor_; +}; + + +/** + * Returns the internal read cursor. + * @param {number} cursor The new cursor. + */ +jspb.BinaryDecoder.prototype.setCursor = function(cursor) { + this.cursor_ = cursor; +}; + + +/** + * Advances the stream cursor by the given number of bytes. + * @param {number} count The number of bytes to advance by. + */ +jspb.BinaryDecoder.prototype.advance = function(count) { + this.cursor_ += count; + goog.asserts.assert(this.cursor_ <= this.end_); +}; + + +/** + * Returns true if this decoder is at the end of the block. + * @return {boolean} + */ +jspb.BinaryDecoder.prototype.atEnd = function() { + return this.cursor_ == this.end_; +}; + + +/** + * Returns true if this decoder is at the end of the block. + * @return {boolean} + */ +jspb.BinaryDecoder.prototype.pastEnd = function() { + return this.cursor_ > this.end_; +}; + + +/** + * Returns true if this decoder encountered an error due to corrupt data. + * @return {boolean} + */ +jspb.BinaryDecoder.prototype.getError = function() { + return this.error_ || + (this.cursor_ < 0) || + (this.cursor_ > this.end_); +}; + + +/** + * Reads an unsigned varint from the binary stream and stores it as a split + * 64-bit integer. Since this does not convert the value to a number, no + * precision is lost. + * + * It's possible for an unsigned varint to be incorrectly encoded - more than + * 64 bits' worth of data could be present. If this happens, this method will + * throw an error. + * + * Decoding varints requires doing some funny base-128 math - for more + * details on the format, see + * https://developers.google.com/protocol-buffers/docs/encoding + * + * @private + */ +jspb.BinaryDecoder.prototype.readSplitVarint64_ = function() { + var temp; + var lowBits = 0; + var highBits = 0; + + // Read the first four bytes of the varint, stopping at the terminator if we + // see it. + for (var i = 0; i < 4; i++) { + temp = this.bytes_[this.cursor_++]; + lowBits |= (temp & 0x7F) << (i * 7); + if (temp < 128) { + this.tempLow_ = lowBits >>> 0; + this.tempHigh_ = 0; + return; + } + } + + // Read the fifth byte, which straddles the low and high dwords. + temp = this.bytes_[this.cursor_++]; + lowBits |= (temp & 0x7F) << 28; + highBits |= (temp & 0x7F) >> 4; + if (temp < 128) { + this.tempLow_ = lowBits >>> 0; + this.tempHigh_ = highBits >>> 0; + return; + } + + // Read the sixth through tenth byte. + for (var i = 0; i < 5; i++) { + temp = this.bytes_[this.cursor_++]; + highBits |= (temp & 0x7F) << (i * 7 + 3); + if (temp < 128) { + this.tempLow_ = lowBits >>> 0; + this.tempHigh_ = highBits >>> 0; + return; + } + } + + // If we did not see the terminator, the encoding was invalid. + goog.asserts.fail('Failed to read varint, encoding is invalid.'); + this.error_ = true; +}; + + +/** + * Skips over a varint in the block without decoding it. + */ +jspb.BinaryDecoder.prototype.skipVarint = function() { + while (this.bytes_[this.cursor_] & 0x80) { + this.cursor_++; + } + this.cursor_++; +}; + + +/** + * Skips backwards over a varint in the block - to do this correctly, we have + * to know the value we're skipping backwards over or things are ambiguous. + * @param {number} value The varint value to unskip. + */ +jspb.BinaryDecoder.prototype.unskipVarint = function(value) { + while (value > 128) { + this.cursor_--; + value = value >>> 7; + } + this.cursor_--; +}; + + +/** + * Reads a 32-bit varint from the binary stream. Due to a quirk of the encoding + * format and Javascript's handling of bitwise math, this actually works + * correctly for both signed and unsigned 32-bit varints. + * + * This function is called vastly more frequently than any other in + * BinaryDecoder, so it has been unrolled and tweaked for performance. + * + * If there are more than 32 bits of data in the varint, it _must_ be due to + * sign-extension. If we're in debug mode and the high 32 bits don't match the + * expected sign extension, this method will throw an error. + * + * Decoding varints requires doing some funny base-128 math - for more + * details on the format, see + * https://developers.google.com/protocol-buffers/docs/encoding + * + * @return {number} The decoded unsigned 32-bit varint. + */ +jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() { + var temp; + var bytes = this.bytes_; + + temp = bytes[this.cursor_ + 0]; + var x = (temp & 0x7F); + if (temp < 128) { + this.cursor_ += 1; + goog.asserts.assert(this.cursor_ <= this.end_); + return x; + } + + temp = bytes[this.cursor_ + 1]; + x |= (temp & 0x7F) << 7; + if (temp < 128) { + this.cursor_ += 2; + goog.asserts.assert(this.cursor_ <= this.end_); + return x; + } + + temp = bytes[this.cursor_ + 2]; + x |= (temp & 0x7F) << 14; + if (temp < 128) { + this.cursor_ += 3; + goog.asserts.assert(this.cursor_ <= this.end_); + return x; + } + + temp = bytes[this.cursor_ + 3]; + x |= (temp & 0x7F) << 21; + if (temp < 128) { + this.cursor_ += 4; + goog.asserts.assert(this.cursor_ <= this.end_); + return x; + } + + temp = bytes[this.cursor_ + 4]; + x |= (temp & 0x0F) << 28; + if (temp < 128) { + // We're reading the high bits of an unsigned varint. The byte we just read + // also contains bits 33 through 35, which we're going to discard. + this.cursor_ += 5; + goog.asserts.assert(this.cursor_ <= this.end_); + return x >>> 0; + } + + // If we get here, we need to truncate coming bytes. However we need to make + // sure cursor place is correct. + this.cursor_ += 5; + if (bytes[this.cursor_++] >= 128 && + bytes[this.cursor_++] >= 128 && + bytes[this.cursor_++] >= 128 && + bytes[this.cursor_++] >= 128 && + bytes[this.cursor_++] >= 128) { + // If we get here, the varint is too long. + goog.asserts.assert(false); + } + + goog.asserts.assert(this.cursor_ <= this.end_); + return x; +}; + + +/** + * The readUnsignedVarint32 above deals with signed 32-bit varints correctly, + * so this is just an alias. + * + * @return {number} The decoded signed 32-bit varint. + */ +jspb.BinaryDecoder.prototype.readSignedVarint32 = + jspb.BinaryDecoder.prototype.readUnsignedVarint32; + + +/** + * Reads a 32-bit unsigned variant and returns its value as a string. + * + * @return {string} The decoded unsigned 32-bit varint as a string. + */ +jspb.BinaryDecoder.prototype.readUnsignedVarint32String = function() { + // 32-bit integers fit in JavaScript numbers without loss of precision, so + // string variants of 32-bit varint readers can simply delegate then convert + // to string. + var value = this.readUnsignedVarint32(); + return value.toString(); +}; + + +/** + * Reads a 32-bit signed variant and returns its value as a string. + * + * @return {string} The decoded signed 32-bit varint as a string. + */ +jspb.BinaryDecoder.prototype.readSignedVarint32String = function() { + // 32-bit integers fit in JavaScript numbers without loss of precision, so + // string variants of 32-bit varint readers can simply delegate then convert + // to string. + var value = this.readSignedVarint32(); + return value.toString(); +}; + + +/** + * Reads a signed, zigzag-encoded 32-bit varint from the binary stream. + * + * Zigzag encoding is a modification of varint encoding that reduces the + * storage overhead for small negative integers - for more details on the + * format, see https://developers.google.com/protocol-buffers/docs/encoding + * + * @return {number} The decoded signed, zigzag-encoded 32-bit varint. + */ +jspb.BinaryDecoder.prototype.readZigzagVarint32 = function() { + var result = this.readUnsignedVarint32(); + return (result >>> 1) ^ - (result & 1); +}; + + +/** + * Reads an unsigned 64-bit varint from the binary stream. Note that since + * Javascript represents all numbers as double-precision floats, there will be + * precision lost if the absolute value of the varint is larger than 2^53. + * + * @return {number} The decoded unsigned varint. Precision will be lost if the + * integer exceeds 2^53. + */ +jspb.BinaryDecoder.prototype.readUnsignedVarint64 = function() { + this.readSplitVarint64_(); + return jspb.utils.joinUint64(this.tempLow_, this.tempHigh_); +}; + + +/** + * Reads an unsigned 64-bit varint from the binary stream and returns the value + * as a decimal string. + * + * @return {string} The decoded unsigned varint as a decimal string. + */ +jspb.BinaryDecoder.prototype.readUnsignedVarint64String = function() { + this.readSplitVarint64_(); + return jspb.utils.joinUnsignedDecimalString(this.tempLow_, this.tempHigh_); +}; + + +/** + * Reads a signed 64-bit varint from the binary stream. Note that since + * Javascript represents all numbers as double-precision floats, there will be + * precision lost if the absolute value of the varint is larger than 2^53. + * + * @return {number} The decoded signed varint. Precision will be lost if the + * integer exceeds 2^53. + */ +jspb.BinaryDecoder.prototype.readSignedVarint64 = function() { + this.readSplitVarint64_(); + return jspb.utils.joinInt64(this.tempLow_, this.tempHigh_); +}; + + +/** + * Reads an signed 64-bit varint from the binary stream and returns the value + * as a decimal string. + * + * @return {string} The decoded signed varint as a decimal string. + */ +jspb.BinaryDecoder.prototype.readSignedVarint64String = function() { + this.readSplitVarint64_(); + return jspb.utils.joinSignedDecimalString(this.tempLow_, this.tempHigh_); +}; + + +/** + * Reads a signed, zigzag-encoded 64-bit varint from the binary stream. Note + * that since Javascript represents all numbers as double-precision floats, + * there will be precision lost if the absolute value of the varint is larger + * than 2^53. + * + * Zigzag encoding is a modification of varint encoding that reduces the + * storage overhead for small negative integers - for more details on the + * format, see https://developers.google.com/protocol-buffers/docs/encoding + * + * @return {number} The decoded zigzag varint. Precision will be lost if the + * integer exceeds 2^53. + */ +jspb.BinaryDecoder.prototype.readZigzagVarint64 = function() { + this.readSplitVarint64_(); + return jspb.utils.joinZigzag64(this.tempLow_, this.tempHigh_); +}; + + +/** + * Reads a signed, zigzag-encoded 64-bit varint from the binary stream and + * returns its valud as a string. + * + * Zigzag encoding is a modification of varint encoding that reduces the + * storage overhead for small negative integers - for more details on the + * format, see https://developers.google.com/protocol-buffers/docs/encoding + * + * @return {string} The decoded signed, zigzag-encoded 64-bit varint as a + * string. + */ +jspb.BinaryDecoder.prototype.readZigzagVarint64String = function() { + // TODO(haberman): write lossless 64-bit zig-zag math. + var value = this.readZigzagVarint64(); + return value.toString(); +}; + + +/** + * Reads a raw unsigned 8-bit integer from the binary stream. + * + * @return {number} The unsigned 8-bit integer read from the binary stream. + */ +jspb.BinaryDecoder.prototype.readUint8 = function() { + var a = this.bytes_[this.cursor_ + 0]; + this.cursor_ += 1; + goog.asserts.assert(this.cursor_ <= this.end_); + return a; +}; + + +/** + * Reads a raw unsigned 16-bit integer from the binary stream. + * + * @return {number} The unsigned 16-bit integer read from the binary stream. + */ +jspb.BinaryDecoder.prototype.readUint16 = function() { + var a = this.bytes_[this.cursor_ + 0]; + var b = this.bytes_[this.cursor_ + 1]; + this.cursor_ += 2; + goog.asserts.assert(this.cursor_ <= this.end_); + return (a << 0) | (b << 8); +}; + + +/** + * Reads a raw unsigned 32-bit integer from the binary stream. + * + * @return {number} The unsigned 32-bit integer read from the binary stream. + */ +jspb.BinaryDecoder.prototype.readUint32 = function() { + var a = this.bytes_[this.cursor_ + 0]; + var b = this.bytes_[this.cursor_ + 1]; + var c = this.bytes_[this.cursor_ + 2]; + var d = this.bytes_[this.cursor_ + 3]; + this.cursor_ += 4; + goog.asserts.assert(this.cursor_ <= this.end_); + return ((a << 0) | (b << 8) | (c << 16) | (d << 24)) >>> 0; +}; + + +/** + * Reads a raw unsigned 64-bit integer from the binary stream. Note that since + * Javascript represents all numbers as double-precision floats, there will be + * precision lost if the absolute value of the integer is larger than 2^53. + * + * @return {number} The unsigned 64-bit integer read from the binary stream. + * Precision will be lost if the integer exceeds 2^53. + */ +jspb.BinaryDecoder.prototype.readUint64 = function() { + var bitsLow = this.readUint32(); + var bitsHigh = this.readUint32(); + return jspb.utils.joinUint64(bitsLow, bitsHigh); +}; + + +/** + * Reads a raw unsigned 64-bit integer from the binary stream. Note that since + * Javascript represents all numbers as double-precision floats, there will be + * precision lost if the absolute value of the integer is larger than 2^53. + * + * @return {string} The unsigned 64-bit integer read from the binary stream. + */ +jspb.BinaryDecoder.prototype.readUint64String = function() { + var bitsLow = this.readUint32(); + var bitsHigh = this.readUint32(); + return jspb.utils.joinUnsignedDecimalString(bitsLow, bitsHigh); +}; + + +/** + * Reads a raw signed 8-bit integer from the binary stream. + * + * @return {number} The signed 8-bit integer read from the binary stream. + */ +jspb.BinaryDecoder.prototype.readInt8 = function() { + var a = this.bytes_[this.cursor_ + 0]; + this.cursor_ += 1; + goog.asserts.assert(this.cursor_ <= this.end_); + return (a << 24) >> 24; +}; + + +/** + * Reads a raw signed 16-bit integer from the binary stream. + * + * @return {number} The signed 16-bit integer read from the binary stream. + */ +jspb.BinaryDecoder.prototype.readInt16 = function() { + var a = this.bytes_[this.cursor_ + 0]; + var b = this.bytes_[this.cursor_ + 1]; + this.cursor_ += 2; + goog.asserts.assert(this.cursor_ <= this.end_); + return (((a << 0) | (b << 8)) << 16) >> 16; +}; + + +/** + * Reads a raw signed 32-bit integer from the binary stream. + * + * @return {number} The signed 32-bit integer read from the binary stream. + */ +jspb.BinaryDecoder.prototype.readInt32 = function() { + var a = this.bytes_[this.cursor_ + 0]; + var b = this.bytes_[this.cursor_ + 1]; + var c = this.bytes_[this.cursor_ + 2]; + var d = this.bytes_[this.cursor_ + 3]; + this.cursor_ += 4; + goog.asserts.assert(this.cursor_ <= this.end_); + return (a << 0) | (b << 8) | (c << 16) | (d << 24); +}; + + +/** + * Reads a raw signed 64-bit integer from the binary stream. Note that since + * Javascript represents all numbers as double-precision floats, there will be + * precision lost if the absolute vlaue of the integer is larger than 2^53. + * + * @return {number} The signed 64-bit integer read from the binary stream. + * Precision will be lost if the integer exceeds 2^53. + */ +jspb.BinaryDecoder.prototype.readInt64 = function() { + var bitsLow = this.readUint32(); + var bitsHigh = this.readUint32(); + return jspb.utils.joinInt64(bitsLow, bitsHigh); +}; + + +/** + * Reads a raw signed 64-bit integer from the binary stream and returns it as a + * string. + * + * @return {string} The signed 64-bit integer read from the binary stream. + * Precision will be lost if the integer exceeds 2^53. + */ +jspb.BinaryDecoder.prototype.readInt64String = function() { + var bitsLow = this.readUint32(); + var bitsHigh = this.readUint32(); + return jspb.utils.joinSignedDecimalString(bitsLow, bitsHigh); +}; + + +/** + * Reads a 32-bit floating-point number from the binary stream, using the + * temporary buffer to realign the data. + * + * @return {number} The float read from the binary stream. + */ +jspb.BinaryDecoder.prototype.readFloat = function() { + var bitsLow = this.readUint32(); + var bitsHigh = 0; + return jspb.utils.joinFloat32(bitsLow, bitsHigh); +}; + + +/** + * Reads a 64-bit floating-point number from the binary stream, using the + * temporary buffer to realign the data. + * + * @return {number} The double read from the binary stream. + */ +jspb.BinaryDecoder.prototype.readDouble = function() { + var bitsLow = this.readUint32(); + var bitsHigh = this.readUint32(); + return jspb.utils.joinFloat64(bitsLow, bitsHigh); +}; + + +/** + * Reads a boolean value from the binary stream. + * @return {boolean} The boolean read from the binary stream. + */ +jspb.BinaryDecoder.prototype.readBool = function() { + return !!this.bytes_[this.cursor_++]; +}; + + +/** + * Reads an enum value from the binary stream, which are always encoded as + * signed varints. + * @return {number} The enum value read from the binary stream. + */ +jspb.BinaryDecoder.prototype.readEnum = function() { + return this.readSignedVarint32(); +}; + + +/** + * Reads and parses a UTF-8 encoded unicode string from the stream. + * The code is inspired by maps.vectortown.parse.StreamedDataViewReader. + * Supports codepoints from U+0000 up to U+10FFFF. + * (http://en.wikipedia.org/wiki/UTF-8). + * @param {number} length The length of the string to read. + * @return {string} The decoded string. + */ +jspb.BinaryDecoder.prototype.readString = function(length) { + var bytes = this.bytes_; + var cursor = this.cursor_; + var end = cursor + length; + var codeUnits = []; + + var result = ''; + while (cursor < end) { + var c = bytes[cursor++]; + if (c < 128) { // Regular 7-bit ASCII. + codeUnits.push(c); + } else if (c < 192) { + // UTF-8 continuation mark. We are out of sync. This + // might happen if we attempted to read a character + // with more than four bytes. + continue; + } else if (c < 224) { // UTF-8 with two bytes. + var c2 = bytes[cursor++]; + codeUnits.push(((c & 31) << 6) | (c2 & 63)); + } else if (c < 240) { // UTF-8 with three bytes. + var c2 = bytes[cursor++]; + var c3 = bytes[cursor++]; + codeUnits.push(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + } else if (c < 248) { // UTF-8 with 4 bytes. + var c2 = bytes[cursor++]; + var c3 = bytes[cursor++]; + var c4 = bytes[cursor++]; + // Characters written on 4 bytes have 21 bits for a codepoint. + // We can't fit that on 16bit characters, so we use surrogates. + var codepoint = ((c & 7) << 18) | ((c2 & 63) << 12) | ((c3 & 63) << 6) | (c4 & 63); + // Surrogates formula from wikipedia. + // 1. Subtract 0x10000 from codepoint + codepoint -= 0x10000; + // 2. Split this into the high 10-bit value and the low 10-bit value + // 3. Add 0xD800 to the high value to form the high surrogate + // 4. Add 0xDC00 to the low value to form the low surrogate: + var low = (codepoint & 1023) + 0xDC00; + var high = ((codepoint >> 10) & 1023) + 0xD800; + codeUnits.push(high, low); + } + + // Avoid exceeding the maximum stack size when calling `apply`. + if (codeUnits.length >= 8192) { + result += String.fromCharCode.apply(null, codeUnits); + codeUnits.length = 0; + } + } + result += goog.crypt.byteArrayToString(codeUnits); + this.cursor_ = cursor; + return result; +}; + + +/** + * Reads and parses a UTF-8 encoded unicode string (with length prefix) from + * the stream. + * @return {string} The decoded string. + */ +jspb.BinaryDecoder.prototype.readStringWithLength = function() { + var length = this.readUnsignedVarint32(); + return this.readString(length); +}; + + +/** + * Reads a block of raw bytes from the binary stream. + * + * @param {number} length The number of bytes to read. + * @return {!Uint8Array} The decoded block of bytes, or an empty block if the + * length was invalid. + */ +jspb.BinaryDecoder.prototype.readBytes = function(length) { + if (length < 0 || + this.cursor_ + length > this.bytes_.length) { + this.error_ = true; + goog.asserts.fail('Invalid byte length!'); + return new Uint8Array(0); + } + + var result = this.bytes_.subarray(this.cursor_, this.cursor_ + length); + + this.cursor_ += length; + goog.asserts.assert(this.cursor_ <= this.end_); + return result; +}; + + +/** + * Reads a 64-bit varint from the stream and returns it as an 8-character + * Unicode string for use as a hash table key. + * + * @return {string} The hash value. + */ +jspb.BinaryDecoder.prototype.readVarintHash64 = function() { + this.readSplitVarint64_(); + return jspb.utils.joinHash64(this.tempLow_, this.tempHigh_); +}; + + +/** + * Reads a 64-bit fixed-width value from the stream and returns it as an + * 8-character Unicode string for use as a hash table key. + * + * @return {string} The hash value. + */ +jspb.BinaryDecoder.prototype.readFixedHash64 = function() { + var bytes = this.bytes_; + var cursor = this.cursor_; + + var a = bytes[cursor + 0]; + var b = bytes[cursor + 1]; + var c = bytes[cursor + 2]; + var d = bytes[cursor + 3]; + var e = bytes[cursor + 4]; + var f = bytes[cursor + 5]; + var g = bytes[cursor + 6]; + var h = bytes[cursor + 7]; + + this.cursor_ += 8; + + return String.fromCharCode(a, b, c, d, e, f, g, h); +}; diff --git a/third_party/protobuf/3.6.0/js/binary/decoder_test.js b/third_party/protobuf/3.6.0/js/binary/decoder_test.js new file mode 100644 index 0000000000..b19e1d1b27 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/binary/decoder_test.js @@ -0,0 +1,359 @@ +// 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()); + }); + + /** + * Tests reading and writing large strings + */ + it('testLargeStrings', function() { + var encoder = new jspb.BinaryEncoder(); + + var len = 150000; + var long_string = ''; + for (var i = 0; i < len; i++) { + long_string += 'a'; + } + + encoder.writeString(long_string); + + var decoder = jspb.BinaryDecoder.alloc(encoder.end()); + + assertEquals(long_string, decoder.readString(len)); + }); + + /** + * Test encoding and decoding utf-8. + */ + it('testUtf8', function() { + var encoder = new jspb.BinaryEncoder(); + + var ascii = "ASCII should work in 3, 2, 1..."; + var utf8_two_bytes = "©"; + var utf8_three_bytes = "❄"; + var utf8_four_bytes = "😁"; + + encoder.writeString(ascii); + encoder.writeString(utf8_two_bytes); + encoder.writeString(utf8_three_bytes); + encoder.writeString(utf8_four_bytes); + + var decoder = jspb.BinaryDecoder.alloc(encoder.end()); + + assertEquals(ascii, decoder.readString(ascii.length)); + assertEquals(utf8_two_bytes, decoder.readString(utf8_two_bytes.length)); + assertEquals(utf8_three_bytes, decoder.readString(utf8_three_bytes.length)); + assertEquals(utf8_four_bytes, decoder.readString(utf8_four_bytes.length)); + }); + + /** + * 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()}); + decoder.reset(); + 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/third_party/protobuf/3.6.0/js/binary/encoder.js b/third_party/protobuf/3.6.0/js/binary/encoder.js new file mode 100644 index 0000000000..b2013f6340 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/binary/encoder.js @@ -0,0 +1,492 @@ +// 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 BinaryEncode defines methods for encoding Javascript values + * into arrays of bytes compatible with the Protocol Buffer wire format. + * + * @author aappleby@google.com (Austin Appleby) + */ + +goog.provide('jspb.BinaryEncoder'); + +goog.require('goog.asserts'); +goog.require('jspb.BinaryConstants'); +goog.require('jspb.utils'); + + + +/** + * BinaryEncoder implements encoders for all the wire types specified in + * https://developers.google.com/protocol-buffers/docs/encoding. + * + * @constructor + * @struct + */ +jspb.BinaryEncoder = function() { + /** @private {!Array<number>} */ + this.buffer_ = []; +}; + + +/** + * @return {number} + */ +jspb.BinaryEncoder.prototype.length = function() { + return this.buffer_.length; +}; + + +/** + * @return {!Array<number>} + */ +jspb.BinaryEncoder.prototype.end = function() { + var buffer = this.buffer_; + this.buffer_ = []; + return buffer; +}; + + +/** + * Encodes a 64-bit integer in 32:32 split representation into its wire-format + * varint representation and stores it in the buffer. + * @param {number} lowBits The low 32 bits of the int. + * @param {number} highBits The high 32 bits of the int. + */ +jspb.BinaryEncoder.prototype.writeSplitVarint64 = function(lowBits, highBits) { + goog.asserts.assert(lowBits == Math.floor(lowBits)); + goog.asserts.assert(highBits == Math.floor(highBits)); + goog.asserts.assert((lowBits >= 0) && + (lowBits < jspb.BinaryConstants.TWO_TO_32)); + goog.asserts.assert((highBits >= 0) && + (highBits < jspb.BinaryConstants.TWO_TO_32)); + + // Break the binary representation into chunks of 7 bits, set the 8th bit + // in each chunk if it's not the final chunk, and append to the result. + while (highBits > 0 || lowBits > 127) { + this.buffer_.push((lowBits & 0x7f) | 0x80); + lowBits = ((lowBits >>> 7) | (highBits << 25)) >>> 0; + highBits = highBits >>> 7; + } + this.buffer_.push(lowBits); +}; + + +/** + * Encodes a 64-bit integer in 32:32 split representation into its wire-format + * fixed representation and stores it in the buffer. + * @param {number} lowBits The low 32 bits of the int. + * @param {number} highBits The high 32 bits of the int. + */ +jspb.BinaryEncoder.prototype.writeSplitFixed64 = function(lowBits, highBits) { + goog.asserts.assert(lowBits == Math.floor(lowBits)); + goog.asserts.assert(highBits == Math.floor(highBits)); + goog.asserts.assert((lowBits >= 0) && + (lowBits < jspb.BinaryConstants.TWO_TO_32)); + goog.asserts.assert((highBits >= 0) && + (highBits < jspb.BinaryConstants.TWO_TO_32)); + this.writeUint32(lowBits); + this.writeUint32(highBits); +}; + + +/** + * Encodes a 32-bit unsigned integer into its wire-format varint representation + * and stores it in the buffer. + * @param {number} value The integer to convert. + */ +jspb.BinaryEncoder.prototype.writeUnsignedVarint32 = function(value) { + goog.asserts.assert(value == Math.floor(value)); + goog.asserts.assert((value >= 0) && + (value < jspb.BinaryConstants.TWO_TO_32)); + + while (value > 127) { + this.buffer_.push((value & 0x7f) | 0x80); + value = value >>> 7; + } + + this.buffer_.push(value); +}; + + +/** + * Encodes a 32-bit signed integer into its wire-format varint representation + * and stores it in the buffer. + * @param {number} value The integer to convert. + */ +jspb.BinaryEncoder.prototype.writeSignedVarint32 = function(value) { + goog.asserts.assert(value == Math.floor(value)); + goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && + (value < jspb.BinaryConstants.TWO_TO_31)); + + // Use the unsigned version if the value is not negative. + if (value >= 0) { + this.writeUnsignedVarint32(value); + return; + } + + // Write nine bytes with a _signed_ right shift so we preserve the sign bit. + for (var i = 0; i < 9; i++) { + this.buffer_.push((value & 0x7f) | 0x80); + value = value >> 7; + } + + // The above loop writes out 63 bits, so the last byte is always the sign bit + // which is always set for negative numbers. + this.buffer_.push(1); +}; + + +/** + * Encodes a 64-bit unsigned integer into its wire-format varint representation + * and stores it in the buffer. Integers that are not representable in 64 bits + * will be truncated. + * @param {number} value The integer to convert. + */ +jspb.BinaryEncoder.prototype.writeUnsignedVarint64 = function(value) { + goog.asserts.assert(value == Math.floor(value)); + goog.asserts.assert((value >= 0) && + (value < jspb.BinaryConstants.TWO_TO_64)); + jspb.utils.splitInt64(value); + this.writeSplitVarint64(jspb.utils.split64Low, + jspb.utils.split64High); +}; + + +/** + * Encodes a 64-bit signed integer into its wire-format varint representation + * and stores it in the buffer. Integers that are not representable in 64 bits + * will be truncated. + * @param {number} value The integer to convert. + */ +jspb.BinaryEncoder.prototype.writeSignedVarint64 = function(value) { + goog.asserts.assert(value == Math.floor(value)); + goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && + (value < jspb.BinaryConstants.TWO_TO_63)); + jspb.utils.splitInt64(value); + this.writeSplitVarint64(jspb.utils.split64Low, + jspb.utils.split64High); +}; + + +/** + * Encodes a JavaScript integer into its wire-format, zigzag-encoded varint + * representation and stores it in the buffer. + * @param {number} value The integer to convert. + */ +jspb.BinaryEncoder.prototype.writeZigzagVarint32 = function(value) { + goog.asserts.assert(value == Math.floor(value)); + goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && + (value < jspb.BinaryConstants.TWO_TO_31)); + this.writeUnsignedVarint32(((value << 1) ^ (value >> 31)) >>> 0); +}; + + +/** + * Encodes a JavaScript integer into its wire-format, zigzag-encoded varint + * representation and stores it in the buffer. Integers not representable in 64 + * bits will be truncated. + * @param {number} value The integer to convert. + */ +jspb.BinaryEncoder.prototype.writeZigzagVarint64 = function(value) { + goog.asserts.assert(value == Math.floor(value)); + goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && + (value < jspb.BinaryConstants.TWO_TO_63)); + jspb.utils.splitZigzag64(value); + this.writeSplitVarint64(jspb.utils.split64Low, + jspb.utils.split64High); +}; + + +/** + * Encodes a JavaScript decimal string into its wire-format, zigzag-encoded + * varint representation and stores it in the buffer. Integers not representable + * in 64 bits will be truncated. + * @param {string} value The integer to convert. + */ +jspb.BinaryEncoder.prototype.writeZigzagVarint64String = function(value) { + // TODO(haberman): write lossless 64-bit zig-zag math. + this.writeZigzagVarint64(parseInt(value, 10)); +}; + + +/** + * Writes a 8-bit unsigned integer to the buffer. Numbers outside the range + * [0,2^8) will be truncated. + * @param {number} value The value to write. + */ +jspb.BinaryEncoder.prototype.writeUint8 = function(value) { + goog.asserts.assert(value == Math.floor(value)); + goog.asserts.assert((value >= 0) && (value < 256)); + this.buffer_.push((value >>> 0) & 0xFF); +}; + + +/** + * Writes a 16-bit unsigned integer to the buffer. Numbers outside the + * range [0,2^16) will be truncated. + * @param {number} value The value to write. + */ +jspb.BinaryEncoder.prototype.writeUint16 = function(value) { + goog.asserts.assert(value == Math.floor(value)); + goog.asserts.assert((value >= 0) && (value < 65536)); + this.buffer_.push((value >>> 0) & 0xFF); + this.buffer_.push((value >>> 8) & 0xFF); +}; + + +/** + * Writes a 32-bit unsigned integer to the buffer. Numbers outside the + * range [0,2^32) will be truncated. + * @param {number} value The value to write. + */ +jspb.BinaryEncoder.prototype.writeUint32 = function(value) { + goog.asserts.assert(value == Math.floor(value)); + goog.asserts.assert((value >= 0) && + (value < jspb.BinaryConstants.TWO_TO_32)); + this.buffer_.push((value >>> 0) & 0xFF); + this.buffer_.push((value >>> 8) & 0xFF); + this.buffer_.push((value >>> 16) & 0xFF); + this.buffer_.push((value >>> 24) & 0xFF); +}; + + +/** + * Writes a 64-bit unsigned integer to the buffer. Numbers outside the + * range [0,2^64) will be truncated. + * @param {number} value The value to write. + */ +jspb.BinaryEncoder.prototype.writeUint64 = function(value) { + goog.asserts.assert(value == Math.floor(value)); + goog.asserts.assert((value >= 0) && + (value < jspb.BinaryConstants.TWO_TO_64)); + jspb.utils.splitUint64(value); + this.writeUint32(jspb.utils.split64Low); + this.writeUint32(jspb.utils.split64High); +}; + + +/** + * Writes a 8-bit integer to the buffer. Numbers outside the range + * [-2^7,2^7) will be truncated. + * @param {number} value The value to write. + */ +jspb.BinaryEncoder.prototype.writeInt8 = function(value) { + goog.asserts.assert(value == Math.floor(value)); + goog.asserts.assert((value >= -128) && (value < 128)); + this.buffer_.push((value >>> 0) & 0xFF); +}; + + +/** + * Writes a 16-bit integer to the buffer. Numbers outside the range + * [-2^15,2^15) will be truncated. + * @param {number} value The value to write. + */ +jspb.BinaryEncoder.prototype.writeInt16 = function(value) { + goog.asserts.assert(value == Math.floor(value)); + goog.asserts.assert((value >= -32768) && (value < 32768)); + this.buffer_.push((value >>> 0) & 0xFF); + this.buffer_.push((value >>> 8) & 0xFF); +}; + + +/** + * Writes a 32-bit integer to the buffer. Numbers outside the range + * [-2^31,2^31) will be truncated. + * @param {number} value The value to write. + */ +jspb.BinaryEncoder.prototype.writeInt32 = function(value) { + goog.asserts.assert(value == Math.floor(value)); + goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && + (value < jspb.BinaryConstants.TWO_TO_31)); + this.buffer_.push((value >>> 0) & 0xFF); + this.buffer_.push((value >>> 8) & 0xFF); + this.buffer_.push((value >>> 16) & 0xFF); + this.buffer_.push((value >>> 24) & 0xFF); +}; + + +/** + * Writes a 64-bit integer to the buffer. Numbers outside the range + * [-2^63,2^63) will be truncated. + * @param {number} value The value to write. + */ +jspb.BinaryEncoder.prototype.writeInt64 = function(value) { + goog.asserts.assert(value == Math.floor(value)); + goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && + (value < jspb.BinaryConstants.TWO_TO_63)); + jspb.utils.splitInt64(value); + this.writeSplitFixed64(jspb.utils.split64Low, jspb.utils.split64High); +}; + + +/** + * Writes a 64-bit integer decimal strings to the buffer. Numbers outside the + * range [-2^63,2^63) will be truncated. + * @param {string} value The value to write. + */ +jspb.BinaryEncoder.prototype.writeInt64String = function(value) { + goog.asserts.assert(value == Math.floor(value)); + goog.asserts.assert((+value >= -jspb.BinaryConstants.TWO_TO_63) && + (+value < jspb.BinaryConstants.TWO_TO_63)); + jspb.utils.splitHash64(jspb.utils.decimalStringToHash64(value)); + this.writeSplitFixed64(jspb.utils.split64Low, jspb.utils.split64High); +}; + + +/** + * Writes a single-precision floating point value to the buffer. Numbers + * requiring more than 32 bits of precision will be truncated. + * @param {number} value The value to write. + */ +jspb.BinaryEncoder.prototype.writeFloat = function(value) { + goog.asserts.assert((value >= -jspb.BinaryConstants.FLOAT32_MAX) && + (value <= jspb.BinaryConstants.FLOAT32_MAX)); + jspb.utils.splitFloat32(value); + this.writeUint32(jspb.utils.split64Low); +}; + + +/** + * Writes a double-precision floating point value to the buffer. As this is + * the native format used by JavaScript, no precision will be lost. + * @param {number} value The value to write. + */ +jspb.BinaryEncoder.prototype.writeDouble = function(value) { + goog.asserts.assert((value >= -jspb.BinaryConstants.FLOAT64_MAX) && + (value <= jspb.BinaryConstants.FLOAT64_MAX)); + jspb.utils.splitFloat64(value); + this.writeUint32(jspb.utils.split64Low); + this.writeUint32(jspb.utils.split64High); +}; + + +/** + * 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.isNumber(value)); + this.buffer_.push(value ? 1 : 0); +}; + + +/** + * Writes an enum value to the buffer as a varint. + * @param {number} value The value to write. + */ +jspb.BinaryEncoder.prototype.writeEnum = function(value) { + goog.asserts.assert(value == Math.floor(value)); + goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && + (value < jspb.BinaryConstants.TWO_TO_31)); + this.writeSignedVarint32(value); +}; + + +/** + * Writes an arbitrary byte array to the buffer. + * @param {!Uint8Array} bytes The array of bytes to write. + */ +jspb.BinaryEncoder.prototype.writeBytes = function(bytes) { + this.buffer_.push.apply(this.buffer_, bytes); +}; + + +/** + * Writes a 64-bit hash string (8 characters @ 8 bits of data each) to the + * buffer as a varint. + * @param {string} hash The hash to write. + */ +jspb.BinaryEncoder.prototype.writeVarintHash64 = function(hash) { + jspb.utils.splitHash64(hash); + this.writeSplitVarint64(jspb.utils.split64Low, + jspb.utils.split64High); +}; + + +/** + * Writes a 64-bit hash string (8 characters @ 8 bits of data each) to the + * buffer as a fixed64. + * @param {string} hash The hash to write. + */ +jspb.BinaryEncoder.prototype.writeFixedHash64 = function(hash) { + jspb.utils.splitHash64(hash); + this.writeUint32(jspb.utils.split64Low); + this.writeUint32(jspb.utils.split64High); +}; + + +/** + * Writes a UTF16 Javascript string to the buffer encoded as UTF8. + * TODO(aappleby): Add support for surrogate pairs, reject unpaired surrogates. + * @param {string} value The string to write. + * @return {number} The number of bytes used to encode the string. + */ +jspb.BinaryEncoder.prototype.writeString = function(value) { + var oldLength = this.buffer_.length; + + for (var i = 0; i < value.length; i++) { + + var c = value.charCodeAt(i); + + if (c < 128) { + this.buffer_.push(c); + } else if (c < 2048) { + this.buffer_.push((c >> 6) | 192); + this.buffer_.push((c & 63) | 128); + } else if (c < 65536) { + // Look for surrogates + if (c >= 0xD800 && c <= 0xDBFF && i + 1 < value.length) { + var second = value.charCodeAt(i + 1); + if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate + // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + c = (c - 0xD800) * 0x400 + second - 0xDC00 + 0x10000; + + this.buffer_.push((c >> 18) | 240); + this.buffer_.push(((c >> 12) & 63 ) | 128); + this.buffer_.push(((c >> 6) & 63) | 128); + this.buffer_.push((c & 63) | 128); + i++; + } + } + else { + this.buffer_.push((c >> 12) | 224); + this.buffer_.push(((c >> 6) & 63) | 128); + this.buffer_.push((c & 63) | 128); + } + } + } + + var length = this.buffer_.length - oldLength; + return length; +}; diff --git a/third_party/protobuf/3.6.0/js/binary/message_test.js b/third_party/protobuf/3.6.0/js/binary/message_test.js new file mode 100644 index 0000000000..4edc666b88 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/binary/message_test.js @@ -0,0 +1,60 @@ +// 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.testing.asserts'); + +// CommonJS-LoadFromFile: test_pb proto.jspb.test +goog.require('proto.jspb.test.Deeply.Nested.Message'); + +// CommonJS-LoadFromFile: test2_pb proto.jspb.test +goog.require('proto.jspb.test.ForeignNestedFieldMessage'); + +describe('Message test suite', function() { + // Verify that we can successfully use a field referring to a nested message + // from a different .proto file. + it('testForeignNestedMessage', function() { + var msg = new proto.jspb.test.ForeignNestedFieldMessage(); + var nested = new proto.jspb.test.Deeply.Nested.Message(); + nested.setCount(5); + msg.setDeeplyNestedMessage(nested); + assertEquals(5, msg.getDeeplyNestedMessage().getCount()); + + // After a serialization-deserialization round trip we should get back the + // same data we started with. + var serialized = msg.serializeBinary(); + var deserialized = + proto.jspb.test.ForeignNestedFieldMessage.deserializeBinary(serialized); + assertEquals(5, deserialized.getDeeplyNestedMessage().getCount()); + }); +}); diff --git a/third_party/protobuf/3.6.0/js/binary/proto_test.js b/third_party/protobuf/3.6.0/js/binary/proto_test.js new file mode 100644 index 0000000000..f5e1b6bbf0 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/binary/proto_test.js @@ -0,0 +1,663 @@ +// 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.BinaryWriter'); +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'); + +// CommonJS-LoadFromFile: ../node_modules/google-protobuf/google/protobuf/any_pb proto.google.protobuf +goog.require('proto.google.protobuf.Any'); + + +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) { + 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]); + + + // Check last so we get more granular errors first. + assertTrue(jspb.Message.equals(original, copy)); +} + + +/** + * Helper: verify that all expected extensions are present. + * @param {!proto.jspb.test.TestExtendable} msg + */ +function checkExtensions(msg) { + assertEquals(0, 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, 0); + 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); + }); + + /** + * Tests that unknown extensions don't cause deserialization failure. + */ + it('testUnknownExtension', function() { + var msg = new proto.jspb.test.TestExtendable(); + fillExtensions(msg); + var writer = new jspb.BinaryWriter(); + writer.writeBool((1 << 29) - 1, true); + proto.jspb.test.TestExtendable.serializeBinaryToWriter(msg, writer); + var encoded = writer.getResultBuffer(); + var decoded = proto.jspb.test.TestExtendable.deserializeBinary(encoded); + checkExtensions(decoded); + }); + + it('testAnyWellKnownType', function() { + var any = new proto.google.protobuf.Any(); + var msg = new proto.jspb.test.TestAllTypes(); + + fillAllFields(msg); + + any.pack(msg.serializeBinary(), 'jspb.test.TestAllTypes'); + + assertEquals('type.googleapis.com/jspb.test.TestAllTypes', + any.getTypeUrl()); + + var msg2 = any.unpack( + proto.jspb.test.TestAllTypes.deserializeBinary, + 'jspb.test.TestAllTypes'); + + checkAllFields(msg, msg2); + }); +}); diff --git a/third_party/protobuf/3.6.0/js/binary/reader.js b/third_party/protobuf/3.6.0/js/binary/reader.js new file mode 100644 index 0000000000..2dc3eb7026 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/binary/reader.js @@ -0,0 +1,1219 @@ +// 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 This file contains utilities for converting binary, + * wire-format protocol buffers into Javascript data structures. + * + * jspb's BinaryReader class wraps the BinaryDecoder class to add methods + * that understand the protocol buffer syntax and can do the type checking and + * bookkeeping necessary to parse trees of nested messages. + * + * Major caveat - Users of this library _must_ keep their Javascript proto + * parsing code in sync with the original .proto file - presumably you'll be + * using the typed jspb code generator, but if you bypass that you'll need + * to keep things in sync by hand. + * + * @author aappleby@google.com (Austin Appleby) + */ + +goog.provide('jspb.BinaryReader'); + +goog.require('goog.asserts'); +goog.require('jspb.BinaryConstants'); +goog.require('jspb.BinaryDecoder'); + + + +/** + * BinaryReader implements the decoders for all the wire types specified in + * https://developers.google.com/protocol-buffers/docs/encoding. + * + * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from. + * @param {number=} opt_start The optional offset to start reading at. + * @param {number=} opt_length The optional length of the block to read - + * we'll throw an assertion if we go off the end of the block. + * @constructor + * @struct + */ +jspb.BinaryReader = function(opt_bytes, opt_start, opt_length) { + /** + * Wire-format decoder. + * @private {!jspb.BinaryDecoder} + */ + this.decoder_ = jspb.BinaryDecoder.alloc(opt_bytes, opt_start, opt_length); + + /** + * Cursor immediately before the field tag. + * @private {number} + */ + this.fieldCursor_ = this.decoder_.getCursor(); + + /** + * Field number of the next field in the buffer, filled in by nextField(). + * @private {number} + */ + this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER; + + /** + * Wire type of the next proto field in the buffer, filled in by + * nextField(). + * @private {jspb.BinaryConstants.WireType} + */ + this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID; + + /** + * Set to true if this reader encountered an error due to corrupt data. + * @private {boolean} + */ + this.error_ = false; + + /** + * User-defined reader callbacks. + * @private {Object<string, function(!jspb.BinaryReader):*>} + */ + this.readCallbacks_ = null; +}; + + +/** + * Global pool of BinaryReader instances. + * @private {!Array<!jspb.BinaryReader>} + */ +jspb.BinaryReader.instanceCache_ = []; + + +/** + * Pops an instance off the instance cache, or creates one if the cache is + * empty. + * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from. + * @param {number=} opt_start The optional offset to start reading at. + * @param {number=} opt_length The optional length of the block to read - + * we'll throw an assertion if we go off the end of the block. + * @return {!jspb.BinaryReader} + */ +jspb.BinaryReader.alloc = + function(opt_bytes, opt_start, opt_length) { + if (jspb.BinaryReader.instanceCache_.length) { + var newReader = jspb.BinaryReader.instanceCache_.pop(); + if (opt_bytes) { + newReader.decoder_.setBlock(opt_bytes, opt_start, opt_length); + } + return newReader; + } else { + return new jspb.BinaryReader(opt_bytes, opt_start, opt_length); + } +}; + + +/** + * Alias for the above method. + * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from. + * @param {number=} opt_start The optional offset to start reading at. + * @param {number=} opt_length The optional length of the block to read - + * we'll throw an assertion if we go off the end of the block. + * @return {!jspb.BinaryReader} + */ +jspb.BinaryReader.prototype.alloc = jspb.BinaryReader.alloc; + + +/** + * Puts this instance back in the instance cache. + */ +jspb.BinaryReader.prototype.free = function() { + this.decoder_.clear(); + this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER; + this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID; + this.error_ = false; + this.readCallbacks_ = null; + + if (jspb.BinaryReader.instanceCache_.length < 100) { + jspb.BinaryReader.instanceCache_.push(this); + } +}; + + +/** + * Returns the cursor immediately before the current field's tag. + * @return {number} The internal read cursor. + */ +jspb.BinaryReader.prototype.getFieldCursor = function() { + return this.fieldCursor_; +}; + + +/** + * Returns the internal read cursor. + * @return {number} The internal read cursor. + */ +jspb.BinaryReader.prototype.getCursor = function() { + return this.decoder_.getCursor(); +}; + + +/** + * Returns the raw buffer. + * @return {?Uint8Array} The raw buffer. + */ +jspb.BinaryReader.prototype.getBuffer = function() { + return this.decoder_.getBuffer(); +}; + + +/** + * @return {number} The field number of the next field in the buffer, or + * INVALID_FIELD_NUMBER if there is no next field. + */ +jspb.BinaryReader.prototype.getFieldNumber = function() { + return this.nextField_; +}; + + +/** + * @return {jspb.BinaryConstants.WireType} The wire type of the next field + * in the stream, or WireType.INVALID if there is no next field. + */ +jspb.BinaryReader.prototype.getWireType = function() { + return this.nextWireType_; +}; + + +/** + * @return {boolean} Whether the current wire type is an end-group tag. Used as + * an exit condition in decoder loops in generated code. + */ +jspb.BinaryReader.prototype.isEndGroup = function() { + return this.nextWireType_ == jspb.BinaryConstants.WireType.END_GROUP; +}; + + +/** + * Returns true if this reader hit an error due to corrupt data. + * @return {boolean} + */ +jspb.BinaryReader.prototype.getError = function() { + return this.error_ || this.decoder_.getError(); +}; + + +/** + * Points this reader at a new block of bytes. + * @param {!Uint8Array} bytes The block of bytes we're reading from. + * @param {number} start The offset to start reading at. + * @param {number} length The length of the block to read. + */ +jspb.BinaryReader.prototype.setBlock = function(bytes, start, length) { + this.decoder_.setBlock(bytes, start, length); + this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER; + this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID; +}; + + +/** + * Rewinds the stream cursor to the beginning of the buffer and resets all + * internal state. + */ +jspb.BinaryReader.prototype.reset = function() { + this.decoder_.reset(); + this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER; + this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID; +}; + + +/** + * Advances the stream cursor by the given number of bytes. + * @param {number} count The number of bytes to advance by. + */ +jspb.BinaryReader.prototype.advance = function(count) { + this.decoder_.advance(count); +}; + + +/** + * Reads the next field header in the stream if there is one, returns true if + * we saw a valid field header or false if we've read the whole stream. + * Throws an error if we encountered a deprecated START_GROUP/END_GROUP field. + * @return {boolean} True if the stream contains more fields. + */ +jspb.BinaryReader.prototype.nextField = function() { + // If we're at the end of the block, there are no more fields. + if (this.decoder_.atEnd()) { + return false; + } + + // If we hit an error decoding the previous field, stop now before we + // try to decode anything else + if (this.getError()) { + goog.asserts.fail('Decoder hit an error'); + return false; + } + + // Otherwise just read the header of the next field. + this.fieldCursor_ = this.decoder_.getCursor(); + var header = this.decoder_.readUnsignedVarint32(); + + var nextField = header >>> 3; + var nextWireType = /** @type {jspb.BinaryConstants.WireType} */ + (header & 0x7); + + // If the wire type isn't one of the valid ones, something's broken. + if (nextWireType != jspb.BinaryConstants.WireType.VARINT && + nextWireType != jspb.BinaryConstants.WireType.FIXED32 && + nextWireType != jspb.BinaryConstants.WireType.FIXED64 && + nextWireType != jspb.BinaryConstants.WireType.DELIMITED && + nextWireType != jspb.BinaryConstants.WireType.START_GROUP && + nextWireType != jspb.BinaryConstants.WireType.END_GROUP) { + goog.asserts.fail('Invalid wire type'); + this.error_ = true; + return false; + } + + this.nextField_ = nextField; + this.nextWireType_ = nextWireType; + + return true; +}; + + +/** + * Winds the reader back to just before this field's header. + */ +jspb.BinaryReader.prototype.unskipHeader = function() { + this.decoder_.unskipVarint((this.nextField_ << 3) | this.nextWireType_); +}; + + +/** + * Skips all contiguous fields whose header matches the one we just read. + */ +jspb.BinaryReader.prototype.skipMatchingFields = function() { + var field = this.nextField_; + this.unskipHeader(); + + while (this.nextField() && (this.getFieldNumber() == field)) { + this.skipField(); + } + + if (!this.decoder_.atEnd()) { + this.unskipHeader(); + } +}; + + +/** + * Skips over the next varint field in the binary stream. + */ +jspb.BinaryReader.prototype.skipVarintField = function() { + if (this.nextWireType_ != jspb.BinaryConstants.WireType.VARINT) { + goog.asserts.fail('Invalid wire type for skipVarintField'); + this.skipField(); + return; + } + + this.decoder_.skipVarint(); +}; + + +/** + * Skips over the next delimited field in the binary stream. + */ +jspb.BinaryReader.prototype.skipDelimitedField = function() { + if (this.nextWireType_ != jspb.BinaryConstants.WireType.DELIMITED) { + goog.asserts.fail('Invalid wire type for skipDelimitedField'); + this.skipField(); + return; + } + + var length = this.decoder_.readUnsignedVarint32(); + this.decoder_.advance(length); +}; + + +/** + * Skips over the next fixed32 field in the binary stream. + */ +jspb.BinaryReader.prototype.skipFixed32Field = function() { + if (this.nextWireType_ != jspb.BinaryConstants.WireType.FIXED32) { + goog.asserts.fail('Invalid wire type for skipFixed32Field'); + this.skipField(); + return; + } + + this.decoder_.advance(4); +}; + + +/** + * Skips over the next fixed64 field in the binary stream. + */ +jspb.BinaryReader.prototype.skipFixed64Field = function() { + if (this.nextWireType_ != jspb.BinaryConstants.WireType.FIXED64) { + goog.asserts.fail('Invalid wire type for skipFixed64Field'); + this.skipField(); + return; + } + + this.decoder_.advance(8); +}; + + +/** + * Skips over the next group field in the binary stream. + */ +jspb.BinaryReader.prototype.skipGroup = function() { + // Keep a stack of start-group tags that must be matched by end-group tags. + var nestedGroups = [this.nextField_]; + do { + if (!this.nextField()) { + goog.asserts.fail('Unmatched start-group tag: stream EOF'); + this.error_ = true; + return; + } + if (this.nextWireType_ == + jspb.BinaryConstants.WireType.START_GROUP) { + // Nested group start. + nestedGroups.push(this.nextField_); + } else if (this.nextWireType_ == + jspb.BinaryConstants.WireType.END_GROUP) { + // Group end: check that it matches top-of-stack. + if (this.nextField_ != nestedGroups.pop()) { + goog.asserts.fail('Unmatched end-group tag'); + this.error_ = true; + return; + } + } + } while (nestedGroups.length > 0); +}; + + +/** + * Skips over the next field in the binary stream - this is useful if we're + * decoding a message that contain unknown fields. + */ +jspb.BinaryReader.prototype.skipField = function() { + switch (this.nextWireType_) { + case jspb.BinaryConstants.WireType.VARINT: + this.skipVarintField(); + break; + case jspb.BinaryConstants.WireType.FIXED64: + this.skipFixed64Field(); + break; + case jspb.BinaryConstants.WireType.DELIMITED: + this.skipDelimitedField(); + break; + case jspb.BinaryConstants.WireType.FIXED32: + this.skipFixed32Field(); + break; + case jspb.BinaryConstants.WireType.START_GROUP: + this.skipGroup(); + break; + default: + goog.asserts.fail('Invalid wire encoding for field.'); + } +}; + + +/** + * Registers a user-defined read callback. + * @param {string} callbackName + * @param {function(!jspb.BinaryReader):*} callback + */ +jspb.BinaryReader.prototype.registerReadCallback = + function(callbackName, callback) { + if (goog.isNull(this.readCallbacks_)) { + this.readCallbacks_ = {}; + } + goog.asserts.assert(!this.readCallbacks_[callbackName]); + this.readCallbacks_[callbackName] = callback; +}; + + +/** + * Runs a registered read callback. + * @param {string} callbackName The name the callback is registered under. + * @return {*} The value returned by the callback. + */ +jspb.BinaryReader.prototype.runReadCallback = function(callbackName) { + goog.asserts.assert(!goog.isNull(this.readCallbacks_)); + var callback = this.readCallbacks_[callbackName]; + goog.asserts.assert(callback); + return callback(this); +}; + + +/** + * Reads a field of any valid non-message type from the binary stream. + * @param {jspb.BinaryConstants.FieldType} fieldType + * @return {jspb.AnyFieldType} + */ +jspb.BinaryReader.prototype.readAny = function(fieldType) { + this.nextWireType_ = jspb.BinaryConstants.FieldTypeToWireType(fieldType); + var fieldTypes = jspb.BinaryConstants.FieldType; + switch (fieldType) { + case fieldTypes.DOUBLE: + return this.readDouble(); + case fieldTypes.FLOAT: + return this.readFloat(); + case fieldTypes.INT64: + return this.readInt64(); + case fieldTypes.UINT64: + return this.readUint64(); + case fieldTypes.INT32: + return this.readInt32(); + case fieldTypes.FIXED64: + return this.readFixed64(); + case fieldTypes.FIXED32: + return this.readFixed32(); + case fieldTypes.BOOL: + return this.readBool(); + case fieldTypes.STRING: + return this.readString(); + case fieldTypes.GROUP: + goog.asserts.fail('Group field type not supported in readAny()'); + case fieldTypes.MESSAGE: + goog.asserts.fail('Message field type not supported in readAny()'); + case fieldTypes.BYTES: + return this.readBytes(); + case fieldTypes.UINT32: + return this.readUint32(); + case fieldTypes.ENUM: + return this.readEnum(); + case fieldTypes.SFIXED32: + return this.readSfixed32(); + case fieldTypes.SFIXED64: + return this.readSfixed64(); + case fieldTypes.SINT32: + return this.readSint32(); + case fieldTypes.SINT64: + return this.readSint64(); + case fieldTypes.FHASH64: + return this.readFixedHash64(); + case fieldTypes.VHASH64: + return this.readVarintHash64(); + default: + goog.asserts.fail('Invalid field type in readAny()'); + } + return 0; +}; + + +/** + * Deserialize a proto into the provided message object using the provided + * reader function. This function is templated as we currently have one client + * who is using manual deserialization instead of the code-generated versions. + * @template T + * @param {T} message + * @param {function(T, !jspb.BinaryReader)} reader + */ +jspb.BinaryReader.prototype.readMessage = function(message, reader) { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); + + // Save the current endpoint of the decoder and move it to the end of the + // embedded message. + var oldEnd = this.decoder_.getEnd(); + var length = this.decoder_.readUnsignedVarint32(); + var newEnd = this.decoder_.getCursor() + length; + this.decoder_.setEnd(newEnd); + + // Deserialize the embedded message. + reader(message, this); + + // Advance the decoder past the embedded message and restore the endpoint. + this.decoder_.setCursor(newEnd); + this.decoder_.setEnd(oldEnd); +}; + + +/** + * Deserialize a proto into the provided message object using the provided + * reader function, assuming that the message is serialized as a group + * with the given tag. + * @template T + * @param {number} field + * @param {T} message + * @param {function(T, !jspb.BinaryReader)} reader + */ +jspb.BinaryReader.prototype.readGroup = + function(field, message, reader) { + // Ensure that the wire type is correct. + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.START_GROUP); + // Ensure that the field number is correct. + goog.asserts.assert(this.nextField_ == field); + + // Deserialize the message. The deserialization will stop at an END_GROUP tag. + reader(message, this); + + if (!this.error_ && + this.nextWireType_ != jspb.BinaryConstants.WireType.END_GROUP) { + goog.asserts.fail('Group submessage did not end with an END_GROUP tag'); + this.error_ = true; + } +}; + + +/** + * Return a decoder that wraps the current delimited field. + * @return {!jspb.BinaryDecoder} + */ +jspb.BinaryReader.prototype.getFieldDecoder = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); + + var length = this.decoder_.readUnsignedVarint32(); + var start = this.decoder_.getCursor(); + var end = start + length; + + var innerDecoder = + jspb.BinaryDecoder.alloc(this.decoder_.getBuffer(), start, length); + this.decoder_.setCursor(end); + return innerDecoder; +}; + + +/** + * Reads a signed 32-bit integer field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * @return {number} The value of the signed 32-bit integer field. + */ +jspb.BinaryReader.prototype.readInt32 = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return this.decoder_.readSignedVarint32(); +}; + + +/** + * Reads a signed 32-bit integer field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * Returns the value as a string. + * + * @return {string} The value of the signed 32-bit integer field as a decimal + * string. + */ +jspb.BinaryReader.prototype.readInt32String = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return this.decoder_.readSignedVarint32String(); +}; + + +/** + * Reads a signed 64-bit integer field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * @return {number} The value of the signed 64-bit integer field. + */ +jspb.BinaryReader.prototype.readInt64 = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return this.decoder_.readSignedVarint64(); +}; + + +/** + * Reads a signed 64-bit integer field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * Returns the value as a string. + * + * @return {string} The value of the signed 64-bit integer field as a decimal + * string. + */ +jspb.BinaryReader.prototype.readInt64String = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return this.decoder_.readSignedVarint64String(); +}; + + +/** + * Reads an unsigned 32-bit integer field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * @return {number} The value of the unsigned 32-bit integer field. + */ +jspb.BinaryReader.prototype.readUint32 = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return this.decoder_.readUnsignedVarint32(); +}; + + +/** + * Reads an unsigned 32-bit integer field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * Returns the value as a string. + * + * @return {string} The value of the unsigned 32-bit integer field as a decimal + * string. + */ +jspb.BinaryReader.prototype.readUint32String = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return this.decoder_.readUnsignedVarint32String(); +}; + + +/** + * Reads an unsigned 64-bit integer field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * @return {number} The value of the unsigned 64-bit integer field. + */ +jspb.BinaryReader.prototype.readUint64 = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return this.decoder_.readUnsignedVarint64(); +}; + + +/** + * Reads an unsigned 64-bit integer field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * Returns the value as a string. + * + * @return {string} The value of the unsigned 64-bit integer field as a decimal + * string. + */ +jspb.BinaryReader.prototype.readUint64String = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return this.decoder_.readUnsignedVarint64String(); +}; + + +/** + * Reads a signed zigzag-encoded 32-bit integer field from the binary stream, + * or throws an error if the next field in the stream is not of the correct + * wire type. + * + * @return {number} The value of the signed 32-bit integer field. + */ +jspb.BinaryReader.prototype.readSint32 = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return this.decoder_.readZigzagVarint32(); +}; + + +/** + * Reads a signed zigzag-encoded 64-bit integer field from the binary stream, + * or throws an error if the next field in the stream is not of the correct + * wire type. + * + * @return {number} The value of the signed 64-bit integer field. + */ +jspb.BinaryReader.prototype.readSint64 = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return this.decoder_.readZigzagVarint64(); +}; + + +/** + * Reads a signed zigzag-encoded 64-bit integer field from the binary stream, + * or throws an error if the next field in the stream is not of the correct + * wire type. + * + * @return {string} The value of the signed 64-bit integer field as a decimal string. + */ +jspb.BinaryReader.prototype.readSint64String = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return this.decoder_.readZigzagVarint64String(); +}; + + +/** + * Reads an unsigned 32-bit fixed-length integer fiield from the binary stream, + * or throws an error if the next field in the stream is not of the correct + * wire type. + * + * @return {number} The value of the double field. + */ +jspb.BinaryReader.prototype.readFixed32 = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32); + return this.decoder_.readUint32(); +}; + + +/** + * Reads an unsigned 64-bit fixed-length integer fiield from the binary stream, + * or throws an error if the next field in the stream is not of the correct + * wire type. + * + * @return {number} The value of the float field. + */ +jspb.BinaryReader.prototype.readFixed64 = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); + return this.decoder_.readUint64(); +}; + + +/** + * Reads a signed 64-bit integer field from the binary stream as a string, or + * throws an error if the next field in the stream is not of the correct wire + * type. + * + * Returns the value as a string. + * + * @return {string} The value of the unsigned 64-bit integer field as a decimal + * string. + */ +jspb.BinaryReader.prototype.readFixed64String = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); + return this.decoder_.readUint64String(); +}; + + +/** + * Reads a signed 32-bit fixed-length integer fiield from the binary stream, or + * throws an error if the next field in the stream is not of the correct wire + * type. + * + * @return {number} The value of the signed 32-bit integer field. + */ +jspb.BinaryReader.prototype.readSfixed32 = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32); + return this.decoder_.readInt32(); +}; + + +/** + * Reads a signed 32-bit fixed-length integer fiield from the binary stream, or + * throws an error if the next field in the stream is not of the correct wire + * type. + * + * @return {string} The value of the signed 32-bit integer field as a decimal + * string. + */ +jspb.BinaryReader.prototype.readSfixed32String = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32); + return this.decoder_.readInt32().toString(); +}; + + +/** + * Reads a signed 64-bit fixed-length integer fiield from the binary stream, or + * throws an error if the next field in the stream is not of the correct wire + * type. + * + * @return {number} The value of the sfixed64 field. + */ +jspb.BinaryReader.prototype.readSfixed64 = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); + return this.decoder_.readInt64(); +}; + + +/** + * Reads a signed 64-bit fixed-length integer fiield from the binary stream, or + * throws an error if the next field in the stream is not of the correct wire + * type. + * + * Returns the value as a string. + * + * @return {string} The value of the sfixed64 field as a decimal string. + */ +jspb.BinaryReader.prototype.readSfixed64String = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); + return this.decoder_.readInt64String(); +}; + + +/** + * Reads a 32-bit floating-point field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * @return {number} The value of the float field. + */ +jspb.BinaryReader.prototype.readFloat = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32); + return this.decoder_.readFloat(); +}; + + +/** + * Reads a 64-bit floating-point field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * @return {number} The value of the double field. + */ +jspb.BinaryReader.prototype.readDouble = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); + return this.decoder_.readDouble(); +}; + + +/** + * Reads a boolean field from the binary stream, or throws an error if the next + * field in the stream is not of the correct wire type. + * + * @return {boolean} The value of the boolean field. + */ +jspb.BinaryReader.prototype.readBool = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return !!this.decoder_.readUnsignedVarint32(); +}; + + +/** + * Reads an enum field from the binary stream, or throws an error if the next + * field in the stream is not of the correct wire type. + * + * @return {number} The value of the enum field. + */ +jspb.BinaryReader.prototype.readEnum = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return this.decoder_.readSignedVarint64(); +}; + + +/** + * Reads a string field from the binary stream, or throws an error if the next + * field in the stream is not of the correct wire type. + * + * @return {string} The value of the string field. + */ +jspb.BinaryReader.prototype.readString = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); + var length = this.decoder_.readUnsignedVarint32(); + return this.decoder_.readString(length); +}; + + +/** + * Reads a length-prefixed block of bytes from the binary stream, or returns + * null if the next field in the stream has an invalid length value. + * + * @return {!Uint8Array} The block of bytes. + */ +jspb.BinaryReader.prototype.readBytes = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); + var length = this.decoder_.readUnsignedVarint32(); + return this.decoder_.readBytes(length); +}; + + +/** + * Reads a 64-bit varint or fixed64 field from the stream and returns it as a + * 8-character Unicode string for use as a hash table key, or throws an error + * if the next field in the stream is not of the correct wire type. + * + * @return {string} The hash value. + */ +jspb.BinaryReader.prototype.readVarintHash64 = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return this.decoder_.readVarintHash64(); +}; + + +/** + * Reads a 64-bit varint or fixed64 field from the stream and returns it as a + * 8-character Unicode string for use as a hash table key, or throws an error + * if the next field in the stream is not of the correct wire type. + * + * @return {string} The hash value. + */ +jspb.BinaryReader.prototype.readFixedHash64 = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); + return this.decoder_.readFixedHash64(); +}; + + +/** + * Reads a packed scalar field using the supplied raw reader function. + * @param {function(this:jspb.BinaryDecoder)} decodeMethod + * @return {!Array} + * @private + */ +jspb.BinaryReader.prototype.readPackedField_ = function(decodeMethod) { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); + var length = this.decoder_.readUnsignedVarint32(); + var end = this.decoder_.getCursor() + length; + var result = []; + while (this.decoder_.getCursor() < end) { + // TODO(aappleby): .call is slow + result.push(decodeMethod.call(this.decoder_)); + } + return result; +}; + + +/** + * Reads a packed int32 field, which consists of a length header and a list of + * signed varints. + * @return {!Array<number>} + */ +jspb.BinaryReader.prototype.readPackedInt32 = function() { + return this.readPackedField_(this.decoder_.readSignedVarint32); +}; + + +/** + * Reads a packed int32 field, which consists of a length header and a list of + * signed varints. Returns a list of strings. + * @return {!Array<string>} + */ +jspb.BinaryReader.prototype.readPackedInt32String = function() { + return this.readPackedField_(this.decoder_.readSignedVarint32String); +}; + + +/** + * Reads a packed int64 field, which consists of a length header and a list of + * signed varints. + * @return {!Array<number>} + */ +jspb.BinaryReader.prototype.readPackedInt64 = function() { + return this.readPackedField_(this.decoder_.readSignedVarint64); +}; + + +/** + * Reads a packed int64 field, which consists of a length header and a list of + * signed varints. Returns a list of strings. + * @return {!Array<string>} + */ +jspb.BinaryReader.prototype.readPackedInt64String = function() { + return this.readPackedField_(this.decoder_.readSignedVarint64String); +}; + + +/** + * Reads a packed uint32 field, which consists of a length header and a list of + * unsigned varints. + * @return {!Array<number>} + */ +jspb.BinaryReader.prototype.readPackedUint32 = function() { + return this.readPackedField_(this.decoder_.readUnsignedVarint32); +}; + + +/** + * Reads a packed uint32 field, which consists of a length header and a list of + * unsigned varints. Returns a list of strings. + * @return {!Array<string>} + */ +jspb.BinaryReader.prototype.readPackedUint32String = function() { + return this.readPackedField_(this.decoder_.readUnsignedVarint32String); +}; + + +/** + * Reads a packed uint64 field, which consists of a length header and a list of + * unsigned varints. + * @return {!Array<number>} + */ +jspb.BinaryReader.prototype.readPackedUint64 = function() { + return this.readPackedField_(this.decoder_.readUnsignedVarint64); +}; + + +/** + * Reads a packed uint64 field, which consists of a length header and a list of + * unsigned varints. Returns a list of strings. + * @return {!Array<string>} + */ +jspb.BinaryReader.prototype.readPackedUint64String = function() { + return this.readPackedField_(this.decoder_.readUnsignedVarint64String); +}; + + +/** + * Reads a packed sint32 field, which consists of a length header and a list of + * zigzag varints. + * @return {!Array<number>} + */ +jspb.BinaryReader.prototype.readPackedSint32 = function() { + return this.readPackedField_(this.decoder_.readZigzagVarint32); +}; + + +/** + * Reads a packed sint64 field, which consists of a length header and a list of + * zigzag varints. + * @return {!Array<number>} + */ +jspb.BinaryReader.prototype.readPackedSint64 = function() { + return this.readPackedField_(this.decoder_.readZigzagVarint64); +}; + + +/** + * Reads a packed sint64 field, which consists of a length header and a list of + * zigzag varints. Returns a list of strings. + * @return {!Array<string>} + */ +jspb.BinaryReader.prototype.readPackedSint64String = function() { + return this.readPackedField_(this.decoder_.readZigzagVarint64String); +}; + + +/** + * Reads a packed fixed32 field, which consists of a length header and a list + * of unsigned 32-bit ints. + * @return {!Array<number>} + */ +jspb.BinaryReader.prototype.readPackedFixed32 = function() { + return this.readPackedField_(this.decoder_.readUint32); +}; + + +/** + * Reads a packed fixed64 field, which consists of a length header and a list + * of unsigned 64-bit ints. + * @return {!Array<number>} + */ +jspb.BinaryReader.prototype.readPackedFixed64 = function() { + return this.readPackedField_(this.decoder_.readUint64); +}; + + +/** + * Reads a packed fixed64 field, which consists of a length header and a list + * of unsigned 64-bit ints. Returns a list of strings. + * @return {!Array<number>} + */ +jspb.BinaryReader.prototype.readPackedFixed64String = function() { + return this.readPackedField_(this.decoder_.readUint64String); +}; + + +/** + * Reads a packed sfixed32 field, which consists of a length header and a list + * of 32-bit ints. + * @return {!Array<number>} + */ +jspb.BinaryReader.prototype.readPackedSfixed32 = function() { + return this.readPackedField_(this.decoder_.readInt32); +}; + + +/** + * Reads a packed sfixed64 field, which consists of a length header and a list + * of 64-bit ints. + * @return {!Array<number>} + */ +jspb.BinaryReader.prototype.readPackedSfixed64 = function() { + return this.readPackedField_(this.decoder_.readInt64); +}; + + +/** + * Reads a packed sfixed64 field, which consists of a length header and a list + * of 64-bit ints. Returns a list of strings. + * @return {!Array<string>} + */ +jspb.BinaryReader.prototype.readPackedSfixed64String = function() { + return this.readPackedField_(this.decoder_.readInt64String); +}; + + +/** + * Reads a packed float field, which consists of a length header and a list of + * floats. + * @return {!Array<number>} + */ +jspb.BinaryReader.prototype.readPackedFloat = function() { + return this.readPackedField_(this.decoder_.readFloat); +}; + + +/** + * Reads a packed double field, which consists of a length header and a list of + * doubles. + * @return {!Array<number>} + */ +jspb.BinaryReader.prototype.readPackedDouble = function() { + return this.readPackedField_(this.decoder_.readDouble); +}; + + +/** + * Reads a packed bool field, which consists of a length header and a list of + * unsigned varints. + * @return {!Array<boolean>} + */ +jspb.BinaryReader.prototype.readPackedBool = function() { + return this.readPackedField_(this.decoder_.readBool); +}; + + +/** + * Reads a packed enum field, which consists of a length header and a list of + * unsigned varints. + * @return {!Array<number>} + */ +jspb.BinaryReader.prototype.readPackedEnum = function() { + return this.readPackedField_(this.decoder_.readEnum); +}; + + +/** + * Reads a packed varint hash64 field, which consists of a length header and a + * list of varint hash64s. + * @return {!Array<string>} + */ +jspb.BinaryReader.prototype.readPackedVarintHash64 = function() { + return this.readPackedField_(this.decoder_.readVarintHash64); +}; + + +/** + * Reads a packed fixed hash64 field, which consists of a length header and a + * list of fixed hash64s. + * @return {!Array<string>} + */ +jspb.BinaryReader.prototype.readPackedFixedHash64 = function() { + return this.readPackedField_(this.decoder_.readFixedHash64); +}; diff --git a/third_party/protobuf/3.6.0/js/binary/reader_test.js b/third_party/protobuf/3.6.0/js/binary/reader_test.js new file mode 100644 index 0000000000..957113859e --- /dev/null +++ b/third_party/protobuf/3.6.0/js/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/third_party/protobuf/3.6.0/js/binary/utils.js b/third_party/protobuf/3.6.0/js/binary/utils.js new file mode 100644 index 0000000000..55a9ccd4ce --- /dev/null +++ b/third_party/protobuf/3.6.0/js/binary/utils.js @@ -0,0 +1,990 @@ +// 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 This file contains helper code used by jspb.BinaryReader + * and BinaryWriter. + * + * @author aappleby@google.com (Austin Appleby) + */ + +goog.provide('jspb.utils'); + +goog.require('goog.asserts'); +goog.require('goog.crypt'); +goog.require('goog.crypt.base64'); +goog.require('goog.string'); +goog.require('jspb.BinaryConstants'); + + +/** + * Javascript can't natively handle 64-bit data types, so to manipulate them we + * have to split them into two 32-bit halves and do the math manually. + * + * Instead of instantiating and passing small structures around to do this, we + * instead just use two global temporary values. This one stores the low 32 + * bits of a split value - for example, if the original value was a 64-bit + * integer, this temporary value will contain the low 32 bits of that integer. + * If the original value was a double, this temporary value will contain the + * low 32 bits of the binary representation of that double, etcetera. + * @type {number} + */ +jspb.utils.split64Low = 0; + + +/** + * And correspondingly, this temporary variable will contain the high 32 bits + * of whatever value was split. + * @type {number} + */ +jspb.utils.split64High = 0; + + +/** + * Splits an unsigned Javascript integer into two 32-bit halves and stores it + * in the temp values above. + * @param {number} value The number to split. + */ +jspb.utils.splitUint64 = function(value) { + // Extract low 32 bits and high 32 bits as unsigned integers. + var lowBits = value >>> 0; + var highBits = Math.floor((value - lowBits) / + jspb.BinaryConstants.TWO_TO_32) >>> 0; + + jspb.utils.split64Low = lowBits; + jspb.utils.split64High = highBits; +}; + + +/** + * Splits a signed Javascript integer into two 32-bit halves and stores it in + * the temp values above. + * @param {number} value The number to split. + */ +jspb.utils.splitInt64 = function(value) { + // Convert to sign-magnitude representation. + var sign = (value < 0); + value = Math.abs(value); + + // Extract low 32 bits and high 32 bits as unsigned integers. + var lowBits = value >>> 0; + var highBits = Math.floor((value - lowBits) / + jspb.BinaryConstants.TWO_TO_32); + highBits = highBits >>> 0; + + // Perform two's complement conversion if the sign bit was set. + if (sign) { + highBits = ~highBits >>> 0; + lowBits = ~lowBits >>> 0; + lowBits += 1; + if (lowBits > 0xFFFFFFFF) { + lowBits = 0; + highBits++; + if (highBits > 0xFFFFFFFF) highBits = 0; + } + } + + jspb.utils.split64Low = lowBits; + jspb.utils.split64High = highBits; +}; + + +/** + * Convers a signed Javascript integer into zigzag format, splits it into two + * 32-bit halves, and stores it in the temp values above. + * @param {number} value The number to split. + */ +jspb.utils.splitZigzag64 = function(value) { + // Convert to sign-magnitude and scale by 2 before we split the value. + var sign = (value < 0); + value = Math.abs(value) * 2; + + jspb.utils.splitUint64(value); + var lowBits = jspb.utils.split64Low; + var highBits = jspb.utils.split64High; + + // If the value is negative, subtract 1 from the split representation so we + // don't lose the sign bit due to precision issues. + if (sign) { + if (lowBits == 0) { + if (highBits == 0) { + lowBits = 0xFFFFFFFF; + highBits = 0xFFFFFFFF; + } else { + highBits--; + lowBits = 0xFFFFFFFF; + } + } else { + lowBits--; + } + } + + jspb.utils.split64Low = lowBits; + jspb.utils.split64High = highBits; +}; + + +/** + * Converts a floating-point number into 32-bit IEEE representation and stores + * it in the temp values above. + * @param {number} value + */ +jspb.utils.splitFloat32 = function(value) { + var sign = (value < 0) ? 1 : 0; + value = sign ? -value : value; + var exp; + var mant; + + // Handle zeros. + if (value === 0) { + if ((1 / value) > 0) { + // Positive zero. + jspb.utils.split64High = 0; + jspb.utils.split64Low = 0x00000000; + } else { + // Negative zero. + jspb.utils.split64High = 0; + jspb.utils.split64Low = 0x80000000; + } + return; + } + + // Handle nans. + if (isNaN(value)) { + jspb.utils.split64High = 0; + jspb.utils.split64Low = 0x7FFFFFFF; + return; + } + + // Handle infinities. + if (value > jspb.BinaryConstants.FLOAT32_MAX) { + jspb.utils.split64High = 0; + jspb.utils.split64Low = ((sign << 31) | (0x7F800000)) >>> 0; + return; + } + + // Handle denormals. + if (value < jspb.BinaryConstants.FLOAT32_MIN) { + // Number is a denormal. + mant = Math.round(value / Math.pow(2, -149)); + jspb.utils.split64High = 0; + jspb.utils.split64Low = ((sign << 31) | mant) >>> 0; + return; + } + + exp = Math.floor(Math.log(value) / Math.LN2); + mant = value * Math.pow(2, -exp); + mant = Math.round(mant * jspb.BinaryConstants.TWO_TO_23) & 0x7FFFFF; + + jspb.utils.split64High = 0; + jspb.utils.split64Low = ((sign << 31) | ((exp + 127) << 23) | mant) >>> 0; +}; + + +/** + * Converts a floating-point number into 64-bit IEEE representation and stores + * it in the temp values above. + * @param {number} value + */ +jspb.utils.splitFloat64 = function(value) { + var sign = (value < 0) ? 1 : 0; + value = sign ? -value : value; + + // Handle zeros. + if (value === 0) { + if ((1 / value) > 0) { + // Positive zero. + jspb.utils.split64High = 0x00000000; + jspb.utils.split64Low = 0x00000000; + } else { + // Negative zero. + jspb.utils.split64High = 0x80000000; + jspb.utils.split64Low = 0x00000000; + } + return; + } + + // Handle nans. + if (isNaN(value)) { + jspb.utils.split64High = 0x7FFFFFFF; + jspb.utils.split64Low = 0xFFFFFFFF; + return; + } + + // Handle infinities. + if (value > jspb.BinaryConstants.FLOAT64_MAX) { + jspb.utils.split64High = ((sign << 31) | (0x7FF00000)) >>> 0; + jspb.utils.split64Low = 0; + return; + } + + // Handle denormals. + if (value < jspb.BinaryConstants.FLOAT64_MIN) { + // Number is a denormal. + var mant = value / Math.pow(2, -1074); + var mantHigh = (mant / jspb.BinaryConstants.TWO_TO_32); + jspb.utils.split64High = ((sign << 31) | mantHigh) >>> 0; + jspb.utils.split64Low = (mant >>> 0); + return; + } + + var exp = Math.floor(Math.log(value) / Math.LN2); + if (exp == 1024) exp = 1023; + var mant = value * Math.pow(2, -exp); + + var mantHigh = (mant * jspb.BinaryConstants.TWO_TO_20) & 0xFFFFF; + var mantLow = (mant * jspb.BinaryConstants.TWO_TO_52) >>> 0; + + jspb.utils.split64High = + ((sign << 31) | ((exp + 1023) << 20) | mantHigh) >>> 0; + jspb.utils.split64Low = mantLow; +}; + + +/** + * Converts an 8-character hash string into two 32-bit numbers and stores them + * in the temp values above. + * @param {string} hash + */ +jspb.utils.splitHash64 = function(hash) { + var a = hash.charCodeAt(0); + var b = hash.charCodeAt(1); + var c = hash.charCodeAt(2); + var d = hash.charCodeAt(3); + var e = hash.charCodeAt(4); + var f = hash.charCodeAt(5); + var g = hash.charCodeAt(6); + var h = hash.charCodeAt(7); + + jspb.utils.split64Low = (a + (b << 8) + (c << 16) + (d << 24)) >>> 0; + jspb.utils.split64High = (e + (f << 8) + (g << 16) + (h << 24)) >>> 0; +}; + + +/** + * Joins two 32-bit values into a 64-bit unsigned integer. Precision will be + * lost if the result is greater than 2^52. + * @param {number} bitsLow + * @param {number} bitsHigh + * @return {number} + */ +jspb.utils.joinUint64 = function(bitsLow, bitsHigh) { + return bitsHigh * jspb.BinaryConstants.TWO_TO_32 + bitsLow; +}; + + +/** + * Joins two 32-bit values into a 64-bit signed integer. Precision will be lost + * if the result is greater than 2^52. + * @param {number} bitsLow + * @param {number} bitsHigh + * @return {number} + */ +jspb.utils.joinInt64 = function(bitsLow, bitsHigh) { + // If the high bit is set, do a manual two's complement conversion. + var sign = (bitsHigh & 0x80000000); + if (sign) { + bitsLow = (~bitsLow + 1) >>> 0; + bitsHigh = ~bitsHigh >>> 0; + if (bitsLow == 0) { + bitsHigh = (bitsHigh + 1) >>> 0; + } + } + + var result = jspb.utils.joinUint64(bitsLow, bitsHigh); + return sign ? -result : result; +}; + + +/** + * Joins two 32-bit values into a 64-bit unsigned integer and applies zigzag + * decoding. Precision will be lost if the result is greater than 2^52. + * @param {number} bitsLow + * @param {number} bitsHigh + * @return {number} + */ +jspb.utils.joinZigzag64 = function(bitsLow, bitsHigh) { + // Extract the sign bit and shift right by one. + var sign = bitsLow & 1; + bitsLow = ((bitsLow >>> 1) | (bitsHigh << 31)) >>> 0; + bitsHigh = bitsHigh >>> 1; + + // Increment the split value if the sign bit was set. + if (sign) { + bitsLow = (bitsLow + 1) >>> 0; + if (bitsLow == 0) { + bitsHigh = (bitsHigh + 1) >>> 0; + } + } + + var result = jspb.utils.joinUint64(bitsLow, bitsHigh); + return sign ? -result : result; +}; + + +/** + * Joins two 32-bit values into a 32-bit IEEE floating point number and + * converts it back into a Javascript number. + * @param {number} bitsLow The low 32 bits of the binary number; + * @param {number} bitsHigh The high 32 bits of the binary number. + * @return {number} + */ +jspb.utils.joinFloat32 = function(bitsLow, bitsHigh) { + var sign = ((bitsLow >> 31) * 2 + 1); + var exp = (bitsLow >>> 23) & 0xFF; + var mant = bitsLow & 0x7FFFFF; + + if (exp == 0xFF) { + if (mant) { + return NaN; + } else { + return sign * Infinity; + } + } + + if (exp == 0) { + // Denormal. + return sign * Math.pow(2, -149) * mant; + } else { + return sign * Math.pow(2, exp - 150) * + (mant + Math.pow(2, 23)); + } +}; + + +/** + * Joins two 32-bit values into a 64-bit IEEE floating point number and + * converts it back into a Javascript number. + * @param {number} bitsLow The low 32 bits of the binary number; + * @param {number} bitsHigh The high 32 bits of the binary number. + * @return {number} + */ +jspb.utils.joinFloat64 = function(bitsLow, bitsHigh) { + var sign = ((bitsHigh >> 31) * 2 + 1); + var exp = (bitsHigh >>> 20) & 0x7FF; + var mant = jspb.BinaryConstants.TWO_TO_32 * (bitsHigh & 0xFFFFF) + bitsLow; + + if (exp == 0x7FF) { + if (mant) { + return NaN; + } else { + return sign * Infinity; + } + } + + if (exp == 0) { + // Denormal. + return sign * Math.pow(2, -1074) * mant; + } else { + return sign * Math.pow(2, exp - 1075) * + (mant + jspb.BinaryConstants.TWO_TO_52); + } +}; + + +/** + * Joins two 32-bit values into an 8-character hash string. + * @param {number} bitsLow + * @param {number} bitsHigh + * @return {string} + */ +jspb.utils.joinHash64 = function(bitsLow, bitsHigh) { + var a = (bitsLow >>> 0) & 0xFF; + var b = (bitsLow >>> 8) & 0xFF; + var c = (bitsLow >>> 16) & 0xFF; + var d = (bitsLow >>> 24) & 0xFF; + var e = (bitsHigh >>> 0) & 0xFF; + var f = (bitsHigh >>> 8) & 0xFF; + var g = (bitsHigh >>> 16) & 0xFF; + var h = (bitsHigh >>> 24) & 0xFF; + + return String.fromCharCode(a, b, c, d, e, f, g, h); +}; + + +/** + * Individual digits for number->string conversion. + * @const {!Array<string>} + */ +jspb.utils.DIGITS = [ + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' +]; + + +/** + * Losslessly converts a 64-bit unsigned integer in 32:32 split representation + * into a decimal string. + * @param {number} bitsLow The low 32 bits of the binary number; + * @param {number} bitsHigh The high 32 bits of the binary number. + * @return {string} The binary number represented as a string. + */ +jspb.utils.joinUnsignedDecimalString = function(bitsLow, bitsHigh) { + // Skip the expensive conversion if the number is small enough to use the + // built-in conversions. + if (bitsHigh <= 0x1FFFFF) { + return '' + (jspb.BinaryConstants.TWO_TO_32 * bitsHigh + bitsLow); + } + + // What this code is doing is essentially converting the input number from + // base-2 to base-1e7, which allows us to represent the 64-bit range with + // only 3 (very large) digits. Those digits are then trivial to convert to + // a base-10 string. + + // The magic numbers used here are - + // 2^24 = 16777216 = (1,6777216) in base-1e7. + // 2^48 = 281474976710656 = (2,8147497,6710656) in base-1e7. + + // Split 32:32 representation into 16:24:24 representation so our + // intermediate digits don't overflow. + var low = bitsLow & 0xFFFFFF; + var mid = (((bitsLow >>> 24) | (bitsHigh << 8)) >>> 0) & 0xFFFFFF; + var high = (bitsHigh >> 16) & 0xFFFF; + + // Assemble our three base-1e7 digits, ignoring carries. The maximum + // value in a digit at this step is representable as a 48-bit integer, which + // can be stored in a 64-bit floating point number. + var digitA = low + (mid * 6777216) + (high * 6710656); + var digitB = mid + (high * 8147497); + var digitC = (high * 2); + + // Apply carries from A to B and from B to C. + var base = 10000000; + if (digitA >= base) { + digitB += Math.floor(digitA / base); + digitA %= base; + } + + if (digitB >= base) { + digitC += Math.floor(digitB / base); + digitB %= base; + } + + // Convert base-1e7 digits to base-10, omitting leading zeroes. + var table = jspb.utils.DIGITS; + var start = false; + var result = ''; + + function emit(digit) { + var temp = base; + for (var i = 0; i < 7; i++) { + temp /= 10; + var decimalDigit = ((digit / temp) % 10) >>> 0; + if ((decimalDigit == 0) && !start) continue; + start = true; + result += table[decimalDigit]; + } + } + + if (digitC || start) emit(digitC); + if (digitB || start) emit(digitB); + if (digitA || start) emit(digitA); + + return result; +}; + + +/** + * Losslessly converts a 64-bit signed integer in 32:32 split representation + * into a decimal string. + * @param {number} bitsLow The low 32 bits of the binary number; + * @param {number} bitsHigh The high 32 bits of the binary number. + * @return {string} The binary number represented as a string. + */ +jspb.utils.joinSignedDecimalString = function(bitsLow, bitsHigh) { + // If we're treating the input as a signed value and the high bit is set, do + // a manual two's complement conversion before the decimal conversion. + var negative = (bitsHigh & 0x80000000); + if (negative) { + bitsLow = (~bitsLow + 1) >>> 0; + var carry = (bitsLow == 0) ? 1 : 0; + bitsHigh = (~bitsHigh + carry) >>> 0; + } + + var result = jspb.utils.joinUnsignedDecimalString(bitsLow, bitsHigh); + return negative ? '-' + result : result; +}; + + +/** + * Convert an 8-character hash string representing either a signed or unsigned + * 64-bit integer into its decimal representation without losing accuracy. + * @param {string} hash The hash string to convert. + * @param {boolean} signed True if we should treat the hash string as encoding + * a signed integer. + * @return {string} + */ +jspb.utils.hash64ToDecimalString = function(hash, signed) { + jspb.utils.splitHash64(hash); + var bitsLow = jspb.utils.split64Low; + var bitsHigh = jspb.utils.split64High; + return signed ? + jspb.utils.joinSignedDecimalString(bitsLow, bitsHigh) : + jspb.utils.joinUnsignedDecimalString(bitsLow, bitsHigh); +}; + + +/** + * Converts an array of 8-character hash strings into their decimal + * representations. + * @param {!Array<string>} hashes The array of hash strings to convert. + * @param {boolean} signed True if we should treat the hash string as encoding + * a signed integer. + * @return {!Array<string>} + */ +jspb.utils.hash64ArrayToDecimalStrings = function(hashes, signed) { + var result = new Array(hashes.length); + for (var i = 0; i < hashes.length; i++) { + result[i] = jspb.utils.hash64ToDecimalString(hashes[i], signed); + } + return result; +}; + + +/** + * Converts a signed or unsigned decimal string into its hash string + * representation. + * @param {string} dec + * @return {string} + */ +jspb.utils.decimalStringToHash64 = function(dec) { + goog.asserts.assert(dec.length > 0); + + // Check for minus sign. + var minus = false; + if (dec[0] === '-') { + minus = true; + dec = dec.slice(1); + } + + // Store result as a byte array. + var resultBytes = [0, 0, 0, 0, 0, 0, 0, 0]; + + // Set result to m*result + c. + function muladd(m, c) { + for (var i = 0; i < 8 && (m !== 1 || c > 0); i++) { + var r = m * resultBytes[i] + c; + resultBytes[i] = r & 0xFF; + c = r >>> 8; + } + } + + // Negate the result bits. + function neg() { + for (var i = 0; i < 8; i++) { + resultBytes[i] = (~resultBytes[i]) & 0xFF; + } + } + + // For each decimal digit, set result to 10*result + digit. + for (var i = 0; i < dec.length; i++) { + muladd(10, jspb.utils.DIGITS.indexOf(dec[i])); + } + + // If there's a minus sign, convert into two's complement. + if (minus) { + neg(); + muladd(1, 1); + } + + return goog.crypt.byteArrayToString(resultBytes); +}; + + +/** + * Converts a signed or unsigned decimal string into two 32-bit halves, and + * stores them in the temp variables listed above. + * @param {string} value The decimal string to convert. + */ +jspb.utils.splitDecimalString = function(value) { + jspb.utils.splitHash64(jspb.utils.decimalStringToHash64(value)); +}; + + +/** + * Converts an 8-character hash string into its hexadecimal representation. + * @param {string} hash + * @return {string} + */ +jspb.utils.hash64ToHexString = function(hash) { + var temp = new Array(18); + temp[0] = '0'; + temp[1] = 'x'; + + for (var i = 0; i < 8; i++) { + var c = hash.charCodeAt(7 - i); + temp[i * 2 + 2] = jspb.utils.DIGITS[c >> 4]; + temp[i * 2 + 3] = jspb.utils.DIGITS[c & 0xF]; + } + + var result = temp.join(''); + return result; +}; + + +/** + * Converts a '0x<16 digits>' hex string into its hash string representation. + * @param {string} hex + * @return {string} + */ +jspb.utils.hexStringToHash64 = function(hex) { + hex = hex.toLowerCase(); + goog.asserts.assert(hex.length == 18); + goog.asserts.assert(hex[0] == '0'); + goog.asserts.assert(hex[1] == 'x'); + + var result = ''; + for (var i = 0; i < 8; i++) { + var hi = jspb.utils.DIGITS.indexOf(hex[i * 2 + 2]); + var lo = jspb.utils.DIGITS.indexOf(hex[i * 2 + 3]); + result = String.fromCharCode(hi * 16 + lo) + result; + } + + return result; +}; + + +/** + * Convert an 8-character hash string representing either a signed or unsigned + * 64-bit integer into a Javascript number. Will lose accuracy if the result is + * larger than 2^52. + * @param {string} hash The hash string to convert. + * @param {boolean} signed True if the has should be interpreted as a signed + * number. + * @return {number} + */ +jspb.utils.hash64ToNumber = function(hash, signed) { + jspb.utils.splitHash64(hash); + var bitsLow = jspb.utils.split64Low; + var bitsHigh = jspb.utils.split64High; + return signed ? jspb.utils.joinInt64(bitsLow, bitsHigh) : + jspb.utils.joinUint64(bitsLow, bitsHigh); +}; + + +/** + * Convert a Javascript number into an 8-character hash string. Will lose + * precision if the value is non-integral or greater than 2^64. + * @param {number} value The integer to convert. + * @return {string} + */ +jspb.utils.numberToHash64 = function(value) { + jspb.utils.splitInt64(value); + return jspb.utils.joinHash64(jspb.utils.split64Low, + jspb.utils.split64High); +}; + + +/** + * Counts the number of contiguous varints in a buffer. + * @param {!Uint8Array} buffer The buffer to scan. + * @param {number} start The starting point in the buffer to scan. + * @param {number} end The end point in the buffer to scan. + * @return {number} The number of varints in the buffer. + */ +jspb.utils.countVarints = function(buffer, start, end) { + // Count how many high bits of each byte were set in the buffer. + var count = 0; + for (var i = start; i < end; i++) { + count += buffer[i] >> 7; + } + + // The number of varints in the buffer equals the size of the buffer minus + // the number of non-terminal bytes in the buffer (those with the high bit + // set). + return (end - start) - count; +}; + + +/** + * Counts the number of contiguous varint fields with the given field number in + * the buffer. + * @param {!Uint8Array} buffer The buffer to scan. + * @param {number} start The starting point in the buffer to scan. + * @param {number} end The end point in the buffer to scan. + * @param {number} field The field number to count. + * @return {number} The number of matching fields in the buffer. + */ +jspb.utils.countVarintFields = function(buffer, start, end, field) { + var count = 0; + var cursor = start; + var tag = field * 8 + jspb.BinaryConstants.WireType.VARINT; + + if (tag < 128) { + // Single-byte field tag, we can use a slightly quicker count. + while (cursor < end) { + // Skip the field tag, or exit if we find a non-matching tag. + if (buffer[cursor++] != tag) return count; + + // Field tag matches, we've found a valid field. + count++; + + // Skip the varint. + while (1) { + var x = buffer[cursor++]; + if ((x & 0x80) == 0) break; + } + } + } else { + while (cursor < end) { + // Skip the field tag, or exit if we find a non-matching tag. + var temp = tag; + while (temp > 128) { + if (buffer[cursor] != ((temp & 0x7F) | 0x80)) return count; + cursor++; + temp >>= 7; + } + if (buffer[cursor++] != temp) return count; + + // Field tag matches, we've found a valid field. + count++; + + // Skip the varint. + while (1) { + var x = buffer[cursor++]; + if ((x & 0x80) == 0) break; + } + } + } + return count; +}; + + +/** + * Counts the number of contiguous fixed32 fields with the given tag in the + * buffer. + * @param {!Uint8Array} buffer The buffer to scan. + * @param {number} start The starting point in the buffer to scan. + * @param {number} end The end point in the buffer to scan. + * @param {number} tag The tag value to count. + * @param {number} stride The number of bytes to skip per field. + * @return {number} The number of fields with a matching tag in the buffer. + * @private + */ +jspb.utils.countFixedFields_ = + function(buffer, start, end, tag, stride) { + var count = 0; + var cursor = start; + + if (tag < 128) { + // Single-byte field tag, we can use a slightly quicker count. + while (cursor < end) { + // Skip the field tag, or exit if we find a non-matching tag. + if (buffer[cursor++] != tag) return count; + + // Field tag matches, we've found a valid field. + count++; + + // Skip the value. + cursor += stride; + } + } else { + while (cursor < end) { + // Skip the field tag, or exit if we find a non-matching tag. + var temp = tag; + while (temp > 128) { + if (buffer[cursor++] != ((temp & 0x7F) | 0x80)) return count; + temp >>= 7; + } + if (buffer[cursor++] != temp) return count; + + // Field tag matches, we've found a valid field. + count++; + + // Skip the value. + cursor += stride; + } + } + return count; +}; + + +/** + * Counts the number of contiguous fixed32 fields with the given field number + * in the buffer. + * @param {!Uint8Array} buffer The buffer to scan. + * @param {number} start The starting point in the buffer to scan. + * @param {number} end The end point in the buffer to scan. + * @param {number} field The field number to count. + * @return {number} The number of matching fields in the buffer. + */ +jspb.utils.countFixed32Fields = function(buffer, start, end, field) { + var tag = field * 8 + jspb.BinaryConstants.WireType.FIXED32; + return jspb.utils.countFixedFields_(buffer, start, end, tag, 4); +}; + + +/** + * Counts the number of contiguous fixed64 fields with the given field number + * in the buffer. + * @param {!Uint8Array} buffer The buffer to scan. + * @param {number} start The starting point in the buffer to scan. + * @param {number} end The end point in the buffer to scan. + * @param {number} field The field number to count + * @return {number} The number of matching fields in the buffer. + */ +jspb.utils.countFixed64Fields = function(buffer, start, end, field) { + var tag = field * 8 + jspb.BinaryConstants.WireType.FIXED64; + return jspb.utils.countFixedFields_(buffer, start, end, tag, 8); +}; + + +/** + * Counts the number of contiguous delimited fields with the given field number + * in the buffer. + * @param {!Uint8Array} buffer The buffer to scan. + * @param {number} start The starting point in the buffer to scan. + * @param {number} end The end point in the buffer to scan. + * @param {number} field The field number to count. + * @return {number} The number of matching fields in the buffer. + */ +jspb.utils.countDelimitedFields = function(buffer, start, end, field) { + var count = 0; + var cursor = start; + var tag = field * 8 + jspb.BinaryConstants.WireType.DELIMITED; + + while (cursor < end) { + // Skip the field tag, or exit if we find a non-matching tag. + var temp = tag; + while (temp > 128) { + if (buffer[cursor++] != ((temp & 0x7F) | 0x80)) return count; + temp >>= 7; + } + if (buffer[cursor++] != temp) return count; + + // Field tag matches, we've found a valid field. + count++; + + // Decode the length prefix. + var length = 0; + var shift = 1; + while (1) { + temp = buffer[cursor++]; + length += (temp & 0x7f) * shift; + shift *= 128; + if ((temp & 0x80) == 0) break; + } + + // Advance the cursor past the blob. + cursor += length; + } + return count; +}; + + +/** + * String-ify bytes for text format. Should be optimized away in non-debug. + * The returned string uses \xXX escapes for all values and is itself quoted. + * [1, 31] serializes to '"\x01\x1f"'. + * @param {jspb.ByteSource} byteSource The bytes to serialize. + * @return {string} Stringified bytes for text format. + */ +jspb.utils.debugBytesToTextFormat = function(byteSource) { + var s = '"'; + if (byteSource) { + var bytes = jspb.utils.byteSourceToUint8Array(byteSource); + for (var i = 0; i < bytes.length; i++) { + s += '\\x'; + if (bytes[i] < 16) s += '0'; + s += bytes[i].toString(16); + } + } + return s + '"'; +}; + + +/** + * String-ify a scalar for text format. Should be optimized away in non-debug. + * @param {string|number|boolean} scalar The scalar to stringify. + * @return {string} Stringified scalar for text format. + */ +jspb.utils.debugScalarToTextFormat = function(scalar) { + if (goog.isString(scalar)) { + return goog.string.quote(scalar); + } else { + return scalar.toString(); + } +}; + + +/** + * Utility function: convert a string with codepoints 0--255 inclusive to a + * Uint8Array. If any codepoints greater than 255 exist in the string, throws an + * exception. + * @param {string} str + * @return {!Uint8Array} + */ +jspb.utils.stringToByteArray = function(str) { + var arr = new Uint8Array(str.length); + for (var i = 0; i < str.length; i++) { + var codepoint = str.charCodeAt(i); + if (codepoint > 255) { + throw new Error('Conversion error: string contains codepoint ' + + 'outside of byte range'); + } + arr[i] = codepoint; + } + return arr; +}; + + +/** + * Converts any type defined in jspb.ByteSource into a Uint8Array. + * @param {!jspb.ByteSource} data + * @return {!Uint8Array} + * @suppress {invalidCasts} + */ +jspb.utils.byteSourceToUint8Array = function(data) { + if (data.constructor === Uint8Array) { + return /** @type {!Uint8Array} */(data); + } + + if (data.constructor === ArrayBuffer) { + data = /** @type {!ArrayBuffer} */(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)); + } + + if (data.constructor === String) { + data = /** @type {string} */(data); + return goog.crypt.base64.decodeStringToUint8Array(data); + } + + goog.asserts.fail('Type not convertible to Uint8Array.'); + return /** @type {!Uint8Array} */(new Uint8Array(0)); +}; diff --git a/third_party/protobuf/3.6.0/js/binary/utils_test.js b/third_party/protobuf/3.6.0/js/binary/utils_test.js new file mode 100644 index 0000000000..1345064470 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/binary/utils_test.js @@ -0,0 +1,669 @@ +// 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'); +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(goog.crypt.byteArrayToString( + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), result); + + result = convert('-1'); + assertEquals(goog.crypt.byteArrayToString( + [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result); + + result = convert('18446744073709551615'); + assertEquals(goog.crypt.byteArrayToString( + [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result); + + result = convert('9223372036854775808'); + assertEquals(goog.crypt.byteArrayToString( + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result); + + result = convert('-9223372036854775808'); + assertEquals(goog.crypt.byteArrayToString( + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result); + + result = convert('123456789123456789'); + assertEquals(goog.crypt.byteArrayToString( + [0x15, 0x5F, 0xD0, 0xAC, 0x4B, 0x9B, 0xB6, 0x01]), result); + + result = convert('-123456789123456789'); + assertEquals(goog.crypt.byteArrayToString( + [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(goog.crypt.byteArrayToString( + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), result); + + result = convert('0xffffffffffffffff'); + assertEquals(goog.crypt.byteArrayToString( + [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result); + + // Hex string is big-endian, hash string is little-endian. + result = convert('0x123456789ABCDEF0'); + assertEquals(goog.crypt.byteArrayToString( + [0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]), result); + + // Capitalization should not matter. + result = convert('0x0000abcdefABCDEF'); + assertEquals(goog.crypt.byteArrayToString( + [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 = goog.crypt.byteArrayToString(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/third_party/protobuf/3.6.0/js/binary/writer.js b/third_party/protobuf/3.6.0/js/binary/writer.js new file mode 100644 index 0000000000..287d29c3f3 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/binary/writer.js @@ -0,0 +1,1594 @@ +// 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 This file contains utilities for encoding Javascript objects + * into binary, wire-format protocol buffers (in the form of Uint8Arrays) that + * a server can consume directly. + * + * jspb's BinaryWriter class defines methods for efficiently encoding + * Javascript objects into binary, wire-format protocol buffers and supports + * all the fundamental field types used in protocol buffers. + * + * Major caveat 1 - Users of this library _must_ keep their Javascript proto + * parsing code in sync with the original .proto file - presumably you'll be + * using the typed jspb code generator, but if you bypass that you'll need + * to keep things in sync by hand. + * + * Major caveat 2 - Javascript is unable to accurately represent integers + * larger than 2^53 due to its use of a double-precision floating point format + * for all numbers. BinaryWriter does not make any special effort to preserve + * precision for values above this limit - if you need to pass 64-bit integers + * (hash codes, for example) between the client and server without precision + * loss, do _not_ use this library. + * + * Major caveat 3 - This class uses typed arrays and must not be used on older + * browsers that do not support them. + * + * @author aappleby@google.com (Austin Appleby) + */ + +goog.provide('jspb.BinaryWriter'); + +goog.require('goog.asserts'); +goog.require('goog.crypt.base64'); +goog.require('jspb.BinaryConstants'); +goog.require('jspb.BinaryEncoder'); +goog.require('jspb.arith.Int64'); +goog.require('jspb.arith.UInt64'); +goog.require('jspb.utils'); + + + +/** + * BinaryWriter implements encoders for all the wire types specified in + * https://developers.google.com/protocol-buffers/docs/encoding. + * + * @constructor + * @struct + */ +jspb.BinaryWriter = function() { + /** + * Blocks of serialized data that will be concatenated once all messages have + * been written. + * @private {!Array<!Uint8Array|!Array<number>>} + */ + this.blocks_ = []; + + /** + * Total number of bytes in the blocks_ array. Does _not_ include bytes in + * the encoder below. + * @private {number} + */ + this.totalLength_ = 0; + + /** + * Binary encoder holding pieces of a message that we're still serializing. + * When we get to a stopping point (either the start of a new submessage, or + * when we need to append a raw Uint8Array), the encoder's buffer will be + * added to the block array above and the encoder will be reset. + * @private {!jspb.BinaryEncoder} + */ + this.encoder_ = new jspb.BinaryEncoder(); + + /** + * A stack of bookmarks containing the parent blocks for each message started + * via beginSubMessage(), needed as bookkeeping for endSubMessage(). + * TODO(aappleby): Deprecated, users should be calling writeMessage(). + * @private {!Array<!Array<number>>} + */ + this.bookmarks_ = []; +}; + + +/** + * Append a typed array of bytes onto the buffer. + * + * @param {!Uint8Array} arr The byte array to append. + * @private + */ +jspb.BinaryWriter.prototype.appendUint8Array_ = function(arr) { + var temp = this.encoder_.end(); + this.blocks_.push(temp); + this.blocks_.push(arr); + this.totalLength_ += temp.length + arr.length; +}; + + +/** + * Begins a new message by writing the field header and returning a bookmark + * which we will use to patch in the message length to in endDelimited_ below. + * @param {number} field + * @return {!Array<number>} + * @private + */ +jspb.BinaryWriter.prototype.beginDelimited_ = function(field) { + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); + var bookmark = this.encoder_.end(); + this.blocks_.push(bookmark); + this.totalLength_ += bookmark.length; + bookmark.push(this.totalLength_); + return bookmark; +}; + + +/** + * Ends a message by encoding the _change_ in length of the buffer to the + * parent block and adds the number of bytes needed to encode that length to + * the total byte length. + * @param {!Array<number>} bookmark + * @private + */ +jspb.BinaryWriter.prototype.endDelimited_ = function(bookmark) { + var oldLength = bookmark.pop(); + var messageLength = this.totalLength_ + this.encoder_.length() - oldLength; + goog.asserts.assert(messageLength >= 0); + + while (messageLength > 127) { + bookmark.push((messageLength & 0x7f) | 0x80); + messageLength = messageLength >>> 7; + this.totalLength_++; + } + + bookmark.push(messageLength); + this.totalLength_++; +}; + + +/** + * Writes a pre-serialized message to the buffer. + * @param {!Uint8Array} bytes The array of bytes to write. + * @param {number} start The start of the range to write. + * @param {number} end The end of the range to write. + */ +jspb.BinaryWriter.prototype.writeSerializedMessage = function( + bytes, start, end) { + this.appendUint8Array_(bytes.subarray(start, end)); +}; + + +/** + * Writes a pre-serialized message to the buffer if the message and endpoints + * are non-null. + * @param {?Uint8Array} bytes The array of bytes to write. + * @param {?number} start The start of the range to write. + * @param {?number} end The end of the range to write. + */ +jspb.BinaryWriter.prototype.maybeWriteSerializedMessage = function( + bytes, start, end) { + if (bytes != null && start != null && end != null) { + this.writeSerializedMessage(bytes, start, end); + } +}; + + +/** + * Resets the writer, throwing away any accumulated buffers. + */ +jspb.BinaryWriter.prototype.reset = function() { + this.blocks_ = []; + this.encoder_.end(); + this.totalLength_ = 0; + this.bookmarks_ = []; +}; + + +/** + * Converts the encoded data into a Uint8Array. + * @return {!Uint8Array} + */ +jspb.BinaryWriter.prototype.getResultBuffer = function() { + goog.asserts.assert(this.bookmarks_.length == 0); + + var flat = new Uint8Array(this.totalLength_ + this.encoder_.length()); + + var blocks = this.blocks_; + var blockCount = blocks.length; + var offset = 0; + + for (var i = 0; i < blockCount; i++) { + var block = blocks[i]; + flat.set(block, offset); + offset += block.length; + } + + var tail = this.encoder_.end(); + flat.set(tail, offset); + offset += tail.length; + + // Post condition: `flattened` must have had every byte written. + goog.asserts.assert(offset == flat.length); + + // Replace our block list with the flattened block, which lets GC reclaim + // the temp blocks sooner. + this.blocks_ = [flat]; + + return flat; +}; + + +/** + * Converts the encoded data into a base64-encoded string. + * @param {boolean=} opt_webSafe True indicates we should use a websafe + * alphabet, which does not require escaping for use in URLs. + * @return {string} + */ +jspb.BinaryWriter.prototype.getResultBase64String = function(opt_webSafe) { + return goog.crypt.base64.encodeByteArray(this.getResultBuffer(), opt_webSafe); +}; + + +/** + * Begins a new sub-message. The client must call endSubMessage() when they're + * done. + * TODO(aappleby): Deprecated. Move callers to writeMessage(). + * @param {number} field The field number of the sub-message. + */ +jspb.BinaryWriter.prototype.beginSubMessage = function(field) { + this.bookmarks_.push(this.beginDelimited_(field)); +}; + + +/** + * Finishes a sub-message and packs it into the parent messages' buffer. + * TODO(aappleby): Deprecated. Move callers to writeMessage(). + */ +jspb.BinaryWriter.prototype.endSubMessage = function() { + goog.asserts.assert(this.bookmarks_.length >= 0); + this.endDelimited_(this.bookmarks_.pop()); +}; + + +/** + * Encodes a (field number, wire type) tuple into a wire-format field header + * and stores it in the buffer as a varint. + * @param {number} field The field number. + * @param {number} wireType The wire-type of the field, as specified in the + * protocol buffer documentation. + * @private + */ +jspb.BinaryWriter.prototype.writeFieldHeader_ = + function(field, wireType) { + goog.asserts.assert(field >= 1 && field == Math.floor(field)); + var x = field * 8 + wireType; + this.encoder_.writeUnsignedVarint32(x); +}; + + +/** + * Writes a field of any valid scalar type to the binary stream. + * @param {jspb.BinaryConstants.FieldType} fieldType + * @param {number} field + * @param {jspb.AnyFieldType} value + */ +jspb.BinaryWriter.prototype.writeAny = function(fieldType, field, value) { + var fieldTypes = jspb.BinaryConstants.FieldType; + switch (fieldType) { + case fieldTypes.DOUBLE: + this.writeDouble(field, /** @type {number} */(value)); + return; + case fieldTypes.FLOAT: + this.writeFloat(field, /** @type {number} */(value)); + return; + case fieldTypes.INT64: + this.writeInt64(field, /** @type {number} */(value)); + return; + case fieldTypes.UINT64: + this.writeUint64(field, /** @type {number} */(value)); + return; + case fieldTypes.INT32: + this.writeInt32(field, /** @type {number} */(value)); + return; + case fieldTypes.FIXED64: + this.writeFixed64(field, /** @type {number} */(value)); + return; + case fieldTypes.FIXED32: + this.writeFixed32(field, /** @type {number} */(value)); + return; + case fieldTypes.BOOL: + this.writeBool(field, /** @type {boolean} */(value)); + return; + case fieldTypes.STRING: + this.writeString(field, /** @type {string} */(value)); + return; + case fieldTypes.GROUP: + goog.asserts.fail('Group field type not supported in writeAny()'); + return; + case fieldTypes.MESSAGE: + goog.asserts.fail('Message field type not supported in writeAny()'); + return; + case fieldTypes.BYTES: + this.writeBytes(field, /** @type {?Uint8Array} */(value)); + return; + case fieldTypes.UINT32: + this.writeUint32(field, /** @type {number} */(value)); + return; + case fieldTypes.ENUM: + this.writeEnum(field, /** @type {number} */(value)); + return; + case fieldTypes.SFIXED32: + this.writeSfixed32(field, /** @type {number} */(value)); + return; + case fieldTypes.SFIXED64: + this.writeSfixed64(field, /** @type {number} */(value)); + return; + case fieldTypes.SINT32: + this.writeSint32(field, /** @type {number} */(value)); + return; + case fieldTypes.SINT64: + this.writeSint64(field, /** @type {number} */(value)); + return; + case fieldTypes.FHASH64: + this.writeFixedHash64(field, /** @type {string} */(value)); + return; + case fieldTypes.VHASH64: + this.writeVarintHash64(field, /** @type {string} */(value)); + return; + default: + goog.asserts.fail('Invalid field type in writeAny()'); + return; + } +}; + + +/** + * Writes a varint field to the buffer without range checking. + * @param {number} field The field number. + * @param {number?} value The value to write. + * @private + */ +jspb.BinaryWriter.prototype.writeUnsignedVarint32_ = function(field, value) { + if (value == null) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); + this.encoder_.writeUnsignedVarint32(value); +}; + + +/** + * Writes a varint field to the buffer without range checking. + * @param {number} field The field number. + * @param {number?} value The value to write. + * @private + */ +jspb.BinaryWriter.prototype.writeSignedVarint32_ = function(field, value) { + if (value == null) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); + this.encoder_.writeSignedVarint32(value); +}; + + +/** + * Writes a varint field to the buffer without range checking. + * @param {number} field The field number. + * @param {number?} value The value to write. + * @private + */ +jspb.BinaryWriter.prototype.writeUnsignedVarint64_ = function(field, value) { + if (value == null) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); + this.encoder_.writeUnsignedVarint64(value); +}; + + +/** + * Writes a varint field to the buffer without range checking. + * @param {number} field The field number. + * @param {number?} value The value to write. + * @private + */ +jspb.BinaryWriter.prototype.writeSignedVarint64_ = function(field, value) { + if (value == null) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); + this.encoder_.writeSignedVarint64(value); +}; + + +/** + * Writes a zigzag varint field to the buffer without range checking. + * @param {number} field The field number. + * @param {number?} value The value to write. + * @private + */ +jspb.BinaryWriter.prototype.writeZigzagVarint32_ = function(field, value) { + if (value == null) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); + this.encoder_.writeZigzagVarint32(value); +}; + + +/** + * Writes a zigzag varint field to the buffer without range checking. + * @param {number} field The field number. + * @param {number?} value The value to write. + * @private + */ +jspb.BinaryWriter.prototype.writeZigzagVarint64_ = function(field, value) { + if (value == null) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); + this.encoder_.writeZigzagVarint64(value); +}; + + +/** + * Writes a zigzag varint field to the buffer without range checking. + * @param {number} field The field number. + * @param {string?} value The value to write. + * @private + */ +jspb.BinaryWriter.prototype.writeZigzagVarint64String_ = function( + field, value) { + if (value == null) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); + this.encoder_.writeZigzagVarint64String(value); +}; + + +/** + * Writes an int32 field to the buffer. Numbers outside the range [-2^31,2^31) + * will be truncated. + * @param {number} field The field number. + * @param {number?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeInt32 = function(field, value) { + if (value == null) return; + goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && + (value < jspb.BinaryConstants.TWO_TO_31)); + this.writeSignedVarint32_(field, value); +}; + + +/** + * Writes an int32 field represented as a string to the buffer. Numbers outside + * the range [-2^31,2^31) will be truncated. + * @param {number} field The field number. + * @param {string?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeInt32String = function(field, value) { + if (value == null) return; + var intValue = /** {number} */ parseInt(value, 10); + goog.asserts.assert((intValue >= -jspb.BinaryConstants.TWO_TO_31) && + (intValue < jspb.BinaryConstants.TWO_TO_31)); + this.writeSignedVarint32_(field, intValue); +}; + + +/** + * Writes an int64 field to the buffer. Numbers outside the range [-2^63,2^63) + * will be truncated. + * @param {number} field The field number. + * @param {number?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeInt64 = function(field, value) { + if (value == null) return; + goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && + (value < jspb.BinaryConstants.TWO_TO_63)); + this.writeSignedVarint64_(field, value); +}; + + +/** + * Writes a int64 field (with value as a string) to the buffer. + * @param {number} field The field number. + * @param {string?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeInt64String = function(field, value) { + if (value == null) return; + var num = jspb.arith.Int64.fromString(value); + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); + this.encoder_.writeSplitVarint64(num.lo, num.hi); +}; + + +/** + * Writes a uint32 field to the buffer. Numbers outside the range [0,2^32) + * will be truncated. + * @param {number} field The field number. + * @param {number?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeUint32 = function(field, value) { + if (value == null) return; + goog.asserts.assert((value >= 0) && + (value < jspb.BinaryConstants.TWO_TO_32)); + this.writeUnsignedVarint32_(field, value); +}; + + +/** + * Writes a uint32 field represented as a string to the buffer. Numbers outside + * the range [0,2^32) will be truncated. + * @param {number} field The field number. + * @param {string?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeUint32String = function(field, value) { + if (value == null) return; + var intValue = /** {number} */ parseInt(value, 10); + goog.asserts.assert((intValue >= 0) && + (intValue < jspb.BinaryConstants.TWO_TO_32)); + this.writeUnsignedVarint32_(field, intValue); +}; + + +/** + * Writes a uint64 field to the buffer. Numbers outside the range [0,2^64) + * will be truncated. + * @param {number} field The field number. + * @param {number?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeUint64 = function(field, value) { + if (value == null) return; + goog.asserts.assert((value >= 0) && + (value < jspb.BinaryConstants.TWO_TO_64)); + this.writeUnsignedVarint64_(field, value); +}; + + +/** + * Writes a uint64 field (with value as a string) to the buffer. + * @param {number} field The field number. + * @param {string?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeUint64String = function(field, value) { + if (value == null) return; + var num = jspb.arith.UInt64.fromString(value); + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); + this.encoder_.writeSplitVarint64(num.lo, num.hi); +}; + + +/** + * Writes a sint32 field to the buffer. Numbers outside the range [-2^31,2^31) + * will be truncated. + * @param {number} field The field number. + * @param {number?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeSint32 = function(field, value) { + if (value == null) return; + goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && + (value < jspb.BinaryConstants.TWO_TO_31)); + this.writeZigzagVarint32_(field, value); +}; + + +/** + * Writes a sint64 field to the buffer. Numbers outside the range [-2^63,2^63) + * will be truncated. + * @param {number} field The field number. + * @param {number?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeSint64 = function(field, value) { + if (value == null) return; + goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && + (value < jspb.BinaryConstants.TWO_TO_63)); + this.writeZigzagVarint64_(field, value); +}; + + +/** + * Writes a sint64 field to the buffer. Numbers outside the range [-2^63,2^63) + * will be truncated. + * @param {number} field The field number. + * @param {string?} value The decimal string to write. + */ +jspb.BinaryWriter.prototype.writeSint64String = function(field, value) { + if (value == null) return; + goog.asserts.assert((+value >= -jspb.BinaryConstants.TWO_TO_63) && + (+value < jspb.BinaryConstants.TWO_TO_63)); + this.writeZigzagVarint64String_(field, value); +}; + + +/** + * Writes a fixed32 field to the buffer. Numbers outside the range [0,2^32) + * will be truncated. + * @param {number} field The field number. + * @param {number?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeFixed32 = function(field, value) { + if (value == null) return; + goog.asserts.assert((value >= 0) && + (value < jspb.BinaryConstants.TWO_TO_32)); + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32); + this.encoder_.writeUint32(value); +}; + + +/** + * Writes a fixed64 field to the buffer. Numbers outside the range [0,2^64) + * will be truncated. + * @param {number} field The field number. + * @param {number?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeFixed64 = function(field, value) { + if (value == null) return; + goog.asserts.assert((value >= 0) && + (value < jspb.BinaryConstants.TWO_TO_64)); + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); + this.encoder_.writeUint64(value); +}; + + +/** + * Writes a fixed64 field (with value as a string) to the buffer. + * @param {number} field The field number. + * @param {string?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeFixed64String = function(field, value) { + if (value == null) return; + var num = jspb.arith.UInt64.fromString(value); + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); + this.encoder_.writeSplitFixed64(num.lo, num.hi); +}; + + +/** + * Writes a sfixed32 field to the buffer. Numbers outside the range + * [-2^31,2^31) will be truncated. + * @param {number} field The field number. + * @param {number?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeSfixed32 = function(field, value) { + if (value == null) return; + goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && + (value < jspb.BinaryConstants.TWO_TO_31)); + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32); + this.encoder_.writeInt32(value); +}; + + +/** + * Writes a sfixed64 field to the buffer. Numbers outside the range + * [-2^63,2^63) will be truncated. + * @param {number} field The field number. + * @param {number?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeSfixed64 = function(field, value) { + if (value == null) return; + goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && + (value < jspb.BinaryConstants.TWO_TO_63)); + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); + this.encoder_.writeInt64(value); +}; + + +/** + * Writes a sfixed64 string field to the buffer. Numbers outside the range + * [-2^63,2^63) will be truncated. + * @param {number} field The field number. + * @param {string?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeSfixed64String = function(field, value) { + if (value == null) return; + var num = jspb.arith.Int64.fromString(value); + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); + this.encoder_.writeSplitFixed64(num.lo, num.hi); +}; + + +/** + * Writes a single-precision floating point field to the buffer. Numbers + * requiring more than 32 bits of precision will be truncated. + * @param {number} field The field number. + * @param {number?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeFloat = function(field, value) { + if (value == null) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32); + this.encoder_.writeFloat(value); +}; + + +/** + * Writes a double-precision floating point field to the buffer. As this is the + * native format used by JavaScript, no precision will be lost. + * @param {number} field The field number. + * @param {number?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeDouble = function(field, value) { + if (value == null) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); + this.encoder_.writeDouble(value); +}; + + +/** + * 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?|number?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeBool = function(field, value) { + if (value == null) return; + goog.asserts.assert(goog.isBoolean(value) || goog.isNumber(value)); + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); + this.encoder_.writeBool(value); +}; + + +/** + * Writes an enum field to the buffer. + * @param {number} field The field number. + * @param {number?} value The value to write. + */ +jspb.BinaryWriter.prototype.writeEnum = function(field, value) { + if (value == null) return; + goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && + (value < jspb.BinaryConstants.TWO_TO_31)); + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); + this.encoder_.writeSignedVarint32(value); +}; + + +/** + * Writes a string field to the buffer. + * @param {number} field The field number. + * @param {string?} value The string to write. + */ +jspb.BinaryWriter.prototype.writeString = function(field, value) { + if (value == null) return; + var bookmark = this.beginDelimited_(field); + this.encoder_.writeString(value); + this.endDelimited_(bookmark); +}; + + +/** + * Writes an arbitrary byte field to the buffer. Note - to match the behavior + * of the C++ implementation, empty byte arrays _are_ serialized. + * @param {number} field The field number. + * @param {?jspb.ByteSource} value The array of bytes to write. + */ +jspb.BinaryWriter.prototype.writeBytes = function(field, value) { + if (value == null) return; + var bytes = jspb.utils.byteSourceToUint8Array(value); + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(bytes.length); + this.appendUint8Array_(bytes); +}; + + +/** + * Writes a message to the buffer. + * @param {number} field The field number. + * @param {?MessageType} value The message to write. + * @param {function(MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback + * Will be invoked with the value to write and the writer to write it with. + * @template MessageType + * Use go/closure-ttl to declare a non-nullable version of MessageType. Replace + * the null in blah|null with none. This is necessary because the compiler will + * infer MessageType to be nullable if the value parameter is nullable. + * @template MessageTypeNonNull := + * cond(isUnknown(MessageType), unknown(), + * mapunion(MessageType, (X) => + * cond(eq(X, 'null'), none(), X))) + * =: + */ +jspb.BinaryWriter.prototype.writeMessage = function( + field, value, writerCallback) { + if (value == null) return; + var bookmark = this.beginDelimited_(field); + writerCallback(value, this); + this.endDelimited_(bookmark); +}; + + +/** + * Writes a group message to the buffer. + * + * @param {number} field The field number. + * @param {?MessageType} value The message to write, wrapped with START_GROUP / + * END_GROUP tags. Will be a no-op if 'value' is null. + * @param {function(MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback + * Will be invoked with the value to write and the writer to write it with. + * @template MessageType + * Use go/closure-ttl to declare a non-nullable version of MessageType. Replace + * the null in blah|null with none. This is necessary because the compiler will + * infer MessageType to be nullable if the value parameter is nullable. + * @template MessageTypeNonNull := + * cond(isUnknown(MessageType), unknown(), + * mapunion(MessageType, (X) => + * cond(eq(X, 'null'), none(), X))) + * =: + */ +jspb.BinaryWriter.prototype.writeGroup = function( + field, value, writerCallback) { + if (value == null) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.START_GROUP); + writerCallback(value, this); + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.END_GROUP); +}; + + +/** + * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to + * the buffer. + * @param {number} field The field number. + * @param {string?} value The hash string. + */ +jspb.BinaryWriter.prototype.writeFixedHash64 = function(field, value) { + if (value == null) return; + goog.asserts.assert(value.length == 8); + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); + this.encoder_.writeFixedHash64(value); +}; + + +/** + * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to + * the buffer. + * @param {number} field The field number. + * @param {string?} value The hash string. + */ +jspb.BinaryWriter.prototype.writeVarintHash64 = function(field, value) { + if (value == null) return; + goog.asserts.assert(value.length == 8); + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); + this.encoder_.writeVarintHash64(value); +}; + + +/** + * Writes an array of numbers to the buffer as a repeated 32-bit int field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedInt32 = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeSignedVarint32_(field, value[i]); + } +}; + + +/** + * Writes an array of numbers formatted as strings to the buffer as a repeated + * 32-bit int field. + * @param {number} field The field number. + * @param {?Array<string>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedInt32String = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeInt32String(field, value[i]); + } +}; + + +/** + * Writes an array of numbers to the buffer as a repeated 64-bit int field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedInt64 = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeSignedVarint64_(field, value[i]); + } +}; + + +/** + * Writes an array of numbers formatted as strings to the buffer as a repeated + * 64-bit int field. + * @param {number} field The field number. + * @param {?Array<string>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedInt64String = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeInt64String(field, value[i]); + } +}; + + +/** + * Writes an array numbers to the buffer as a repeated unsigned 32-bit int + * field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedUint32 = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeUnsignedVarint32_(field, value[i]); + } +}; + + +/** + * Writes an array of numbers formatted as strings to the buffer as a repeated + * unsigned 32-bit int field. + * @param {number} field The field number. + * @param {?Array<string>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedUint32String = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeUint32String(field, value[i]); + } +}; + + +/** + * Writes an array numbers to the buffer as a repeated unsigned 64-bit int + * field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedUint64 = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeUnsignedVarint64_(field, value[i]); + } +}; + + +/** + * Writes an array of numbers formatted as strings to the buffer as a repeated + * unsigned 64-bit int field. + * @param {number} field The field number. + * @param {?Array<string>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedUint64String = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeUint64String(field, value[i]); + } +}; + + +/** + * Writes an array numbers to the buffer as a repeated signed 32-bit int field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedSint32 = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeZigzagVarint32_(field, value[i]); + } +}; + + +/** + * Writes an array numbers to the buffer as a repeated signed 64-bit int field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedSint64 = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeZigzagVarint64_(field, value[i]); + } +}; + + +/** + * Writes an array numbers to the buffer as a repeated signed 64-bit int field. + * @param {number} field The field number. + * @param {?Array<string>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedSint64String = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeZigzagVarint64String_(field, value[i]); + } +}; + + +/** + * Writes an array of numbers to the buffer as a repeated fixed32 field. This + * works for both signed and unsigned fixed32s. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedFixed32 = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeFixed32(field, value[i]); + } +}; + + +/** + * Writes an array of numbers to the buffer as a repeated fixed64 field. This + * works for both signed and unsigned fixed64s. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedFixed64 = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeFixed64(field, value[i]); + } +}; + + +/** + * Writes an array of numbers to the buffer as a repeated fixed64 field. This + * works for both signed and unsigned fixed64s. + * @param {number} field The field number. + * @param {?Array<string>} value The array of decimal strings to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedFixed64String = function( + field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeFixed64String(field, value[i]); + } +}; + + +/** + * Writes an array of numbers to the buffer as a repeated sfixed32 field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedSfixed32 = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeSfixed32(field, value[i]); + } +}; + + +/** + * Writes an array of numbers to the buffer as a repeated sfixed64 field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedSfixed64 = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeSfixed64(field, value[i]); + } +}; + + +/** + * Writes an array of decimal strings to the buffer as a repeated sfixed64 + * field. + * @param {number} field The field number. + * @param {?Array<string>} value The array of decimal strings to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedSfixed64String = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeSfixed64String(field, value[i]); + } +}; + + +/** + * Writes an array of numbers to the buffer as a repeated float field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedFloat = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeFloat(field, value[i]); + } +}; + + +/** + * Writes an array of numbers to the buffer as a repeated double field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedDouble = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeDouble(field, value[i]); + } +}; + + +/** + * Writes an array of booleans to the buffer as a repeated bool field. + * @param {number} field The field number. + * @param {?Array<boolean>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedBool = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeBool(field, value[i]); + } +}; + + +/** + * Writes an array of enums to the buffer as a repeated enum field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedEnum = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeEnum(field, value[i]); + } +}; + + +/** + * Writes an array of strings to the buffer as a repeated string field. + * @param {number} field The field number. + * @param {?Array<string>} value The array of strings to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedString = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeString(field, value[i]); + } +}; + + +/** + * Writes an array of arbitrary byte fields to the buffer. + * @param {number} field The field number. + * @param {?Array<!jspb.ByteSource>} value The arrays of arrays of bytes to + * write. + */ +jspb.BinaryWriter.prototype.writeRepeatedBytes = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeBytes(field, value[i]); + } +}; + + +/** + * Writes an array of messages to the buffer. + * @template MessageType + * @param {number} field The field number. + * @param {?Array<MessageType>} value The array of messages to + * write. + * @param {function(MessageType, !jspb.BinaryWriter)} writerCallback + * Will be invoked with the value to write and the writer to write it with. + */ +jspb.BinaryWriter.prototype.writeRepeatedMessage = function( + field, value, writerCallback) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + var bookmark = this.beginDelimited_(field); + writerCallback(value[i], this); + this.endDelimited_(bookmark); + } +}; + + +/** + * Writes an array of group messages to the buffer. + * @template MessageType + * @param {number} field The field number. + * @param {?Array<MessageType>} value The array of messages to + * write. + * @param {function(MessageType, !jspb.BinaryWriter)} writerCallback + * Will be invoked with the value to write and the writer to write it with. + */ +jspb.BinaryWriter.prototype.writeRepeatedGroup = function( + field, value, writerCallback) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.START_GROUP); + writerCallback(value[i], this); + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.END_GROUP); + } +}; + + +/** + * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to + * the buffer. + * @param {number} field The field number. + * @param {?Array<string>} value The array of hashes to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedFixedHash64 = + function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeFixedHash64(field, value[i]); + } +}; + + +/** + * Writes a repeated 64-bit hash string field (8 characters @ 8 bits of data + * each) to the buffer. + * @param {number} field The field number. + * @param {?Array<string>} value The array of hashes to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedVarintHash64 = + function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeVarintHash64(field, value[i]); + } +}; + + +/** + * Writes an array of numbers to the buffer as a packed 32-bit int field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writePackedInt32 = function(field, value) { + if (value == null || !value.length) return; + var bookmark = this.beginDelimited_(field); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeSignedVarint32(value[i]); + } + this.endDelimited_(bookmark); +}; + + +/** + * Writes an array of numbers represented as strings to the buffer as a packed + * 32-bit int field. + * @param {number} field + * @param {?Array<string>} value + */ +jspb.BinaryWriter.prototype.writePackedInt32String = function(field, value) { + if (value == null || !value.length) return; + var bookmark = this.beginDelimited_(field); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeSignedVarint32(parseInt(value[i], 10)); + } + this.endDelimited_(bookmark); +}; + + +/** + * Writes an array of numbers to the buffer as a packed 64-bit int field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writePackedInt64 = function(field, value) { + if (value == null || !value.length) return; + var bookmark = this.beginDelimited_(field); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeSignedVarint64(value[i]); + } + this.endDelimited_(bookmark); +}; + + +/** + * Writes an array of numbers represented as strings to the buffer as a packed + * 64-bit int field. + * @param {number} field + * @param {?Array<string>} value + */ +jspb.BinaryWriter.prototype.writePackedInt64String = function(field, value) { + if (value == null || !value.length) return; + var bookmark = this.beginDelimited_(field); + for (var i = 0; i < value.length; i++) { + var num = jspb.arith.Int64.fromString(value[i]); + this.encoder_.writeSplitVarint64(num.lo, num.hi); + } + this.endDelimited_(bookmark); +}; + + +/** + * Writes an array numbers to the buffer as a packed unsigned 32-bit int field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writePackedUint32 = function(field, value) { + if (value == null || !value.length) return; + var bookmark = this.beginDelimited_(field); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeUnsignedVarint32(value[i]); + } + this.endDelimited_(bookmark); +}; + + +/** + * Writes an array of numbers represented as strings to the buffer as a packed + * unsigned 32-bit int field. + * @param {number} field + * @param {?Array<string>} value + */ +jspb.BinaryWriter.prototype.writePackedUint32String = + function(field, value) { + if (value == null || !value.length) return; + var bookmark = this.beginDelimited_(field); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeUnsignedVarint32(parseInt(value[i], 10)); + } + this.endDelimited_(bookmark); +}; + + +/** + * Writes an array numbers to the buffer as a packed unsigned 64-bit int field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writePackedUint64 = function(field, value) { + if (value == null || !value.length) return; + var bookmark = this.beginDelimited_(field); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeUnsignedVarint64(value[i]); + } + this.endDelimited_(bookmark); +}; + + +/** + * Writes an array of numbers represented as strings to the buffer as a packed + * unsigned 64-bit int field. + * @param {number} field + * @param {?Array<string>} value + */ +jspb.BinaryWriter.prototype.writePackedUint64String = + function(field, value) { + if (value == null || !value.length) return; + var bookmark = this.beginDelimited_(field); + for (var i = 0; i < value.length; i++) { + var num = jspb.arith.UInt64.fromString(value[i]); + this.encoder_.writeSplitVarint64(num.lo, num.hi); + } + this.endDelimited_(bookmark); +}; + + +/** + * Writes an array numbers to the buffer as a packed signed 32-bit int field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writePackedSint32 = function(field, value) { + if (value == null || !value.length) return; + var bookmark = this.beginDelimited_(field); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeZigzagVarint32(value[i]); + } + this.endDelimited_(bookmark); +}; + + +/** + * Writes an array of numbers to the buffer as a packed signed 64-bit int field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writePackedSint64 = function(field, value) { + if (value == null || !value.length) return; + var bookmark = this.beginDelimited_(field); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeZigzagVarint64(value[i]); + } + this.endDelimited_(bookmark); +}; + + +/** + * Writes an array of decimal strings to the buffer as a packed signed 64-bit + * int field. + * @param {number} field The field number. + * @param {?Array<string>} value The array of decimal strings to write. + */ +jspb.BinaryWriter.prototype.writePackedSint64String = function(field, value) { + if (value == null || !value.length) return; + var bookmark = this.beginDelimited_(field); + for (var i = 0; i < value.length; i++) { + // TODO(haberman): make lossless + this.encoder_.writeZigzagVarint64(parseInt(value[i], 10)); + } + this.endDelimited_(bookmark); +}; + + +/** + * Writes an array of numbers to the buffer as a packed fixed32 field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writePackedFixed32 = function(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length * 4); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeUint32(value[i]); + } +}; + + +/** + * Writes an array of numbers to the buffer as a packed fixed64 field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writePackedFixed64 = function(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length * 8); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeUint64(value[i]); + } +}; + + +/** + * Writes an array of numbers represented as strings to the buffer as a packed + * fixed64 field. + * @param {number} field The field number. + * @param {?Array<string>} value The array of strings to write. + */ +jspb.BinaryWriter.prototype.writePackedFixed64String = function(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length * 8); + for (var i = 0; i < value.length; i++) { + var num = jspb.arith.UInt64.fromString(value[i]); + this.encoder_.writeSplitFixed64(num.lo, num.hi); + } +}; + + +/** + * Writes an array of numbers to the buffer as a packed sfixed32 field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writePackedSfixed32 = function(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length * 4); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeInt32(value[i]); + } +}; + + +/** + * Writes an array of numbers to the buffer as a packed sfixed64 field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writePackedSfixed64 = function(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length * 8); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeInt64(value[i]); + } +}; + + +/** + * Writes an array of numbers to the buffer as a packed sfixed64 field. + * @param {number} field The field number. + * @param {?Array<string>} value The array of decimal strings to write. + */ +jspb.BinaryWriter.prototype.writePackedSfixed64String = function(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length * 8); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeInt64String(value[i]); + } +}; + + +/** + * Writes an array of numbers to the buffer as a packed float field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writePackedFloat = function(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length * 4); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeFloat(value[i]); + } +}; + + +/** + * Writes an array of numbers to the buffer as a packed double field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writePackedDouble = function(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length * 8); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeDouble(value[i]); + } +}; + + +/** + * Writes an array of booleans to the buffer as a packed bool field. + * @param {number} field The field number. + * @param {?Array<boolean>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writePackedBool = function(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeBool(value[i]); + } +}; + + +/** + * Writes an array of enums to the buffer as a packed enum field. + * @param {number} field The field number. + * @param {?Array<number>} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writePackedEnum = function(field, value) { + if (value == null || !value.length) return; + var bookmark = this.beginDelimited_(field); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeEnum(value[i]); + } + this.endDelimited_(bookmark); +}; + + +/** + * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to + * the buffer. + * @param {number} field The field number. + * @param {?Array<string>} value The array of hashes to write. + */ +jspb.BinaryWriter.prototype.writePackedFixedHash64 = function(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length * 8); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeFixedHash64(value[i]); + } +}; + + +/** + * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to + * the buffer. + * @param {number} field The field number. + * @param {?Array<string>} value The array of hashes to write. + */ +jspb.BinaryWriter.prototype.writePackedVarintHash64 = function(field, value) { + if (value == null || !value.length) return; + var bookmark = this.beginDelimited_(field); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeVarintHash64(value[i]); + } + this.endDelimited_(bookmark); +}; diff --git a/third_party/protobuf/3.6.0/js/binary/writer_test.js b/third_party/protobuf/3.6.0/js/binary/writer_test.js new file mode 100644 index 0000000000..8a9a1bb009 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/binary/writer_test.js @@ -0,0 +1,133 @@ +// 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) { + assertThrows(func); +} + + +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)); + }); + + + /** + * Tests websafe encodings for base64 strings. + */ + it('testWebSafeOption', function() { + var writer = new jspb.BinaryWriter(); + writer.writeBytes(1, new Uint8Array([127])); + assertEquals('CgF/', writer.getResultBase64String()); + assertEquals('CgF/', writer.getResultBase64String(false)); + assertEquals('CgF_', writer.getResultBase64String(true)); + }); +}); diff --git a/third_party/protobuf/3.6.0/js/commonjs/export.js b/third_party/protobuf/3.6.0/js/commonjs/export.js new file mode 100644 index 0000000000..a93ee928ff --- /dev/null +++ b/third_party/protobuf/3.6.0/js/commonjs/export.js @@ -0,0 +1,31 @@ +/** + * @fileoverview Export symbols needed by generated code in CommonJS style. + * + * This effectively is our canonical list of what we publicly export from + * the google-protobuf.js file that we build at distribution time. + */ + +// Include a dummy provide statement so that closurebuilder.py does not skip over this +// file. +goog.provide('jspb.Export'); + +goog.require('goog.object'); +goog.require('jspb.BinaryReader'); +goog.require('jspb.BinaryWriter'); +goog.require('jspb.ExtensionFieldBinaryInfo'); +goog.require('jspb.ExtensionFieldInfo'); +goog.require('jspb.Message'); +goog.require('jspb.Map'); + +exports.Map = jspb.Map; +exports.Message = jspb.Message; +exports.BinaryReader = jspb.BinaryReader; +exports.BinaryWriter = jspb.BinaryWriter; +exports.ExtensionFieldInfo = jspb.ExtensionFieldInfo; +exports.ExtensionFieldBinaryInfo = jspb.ExtensionFieldBinaryInfo; + +// These are used by generated code but should not be used directly by clients. +exports.exportSymbol = goog.exportSymbol; +exports.inherits = goog.inherits; +exports.object = {extend: goog.object.extend}; +exports.typeOf = goog.typeOf; diff --git a/third_party/protobuf/3.6.0/js/commonjs/export_asserts.js b/third_party/protobuf/3.6.0/js/commonjs/export_asserts.js new file mode 100644 index 0000000000..ad9446c74a --- /dev/null +++ b/third_party/protobuf/3.6.0/js/commonjs/export_asserts.js @@ -0,0 +1,41 @@ +/** + * @fileoverview Exports symbols needed only by tests. + * + * This file exports several Closure Library symbols that are only + * used by tests. It is used to generate a file + * closure_asserts_commonjs.js that is only used at testing time. + */ + +// Include a dummy provide statement so that closurebuilder.py does not skip over this +// file. +goog.provide('jspb.ExportAsserts'); + +goog.require('goog.testing.asserts'); + +var global = Function('return this')(); + +// All of the closure "assert" functions are exported at the global level. +// +// The Google Closure assert functions start with assert, eg. +// assertThrows +// assertNotThrows +// assertTrue +// ... +// +// The one exception is the "fail" function. +function shouldExport(str) { + return str.lastIndexOf('assert') === 0 || str == 'fail'; +} + +for (var key in global) { + if ((typeof key == "string") && global.hasOwnProperty(key) && + shouldExport(key)) { + exports[key] = global[key]; + } +} + +// The COMPILED variable is set by Closure compiler to "true" when it compiles +// JavaScript, so in practice this is equivalent to "exports.COMPILED = true". +// This will disable some debugging functionality in debug.js. We could +// investigate whether this can/should be enabled in CommonJS builds. +exports.COMPILED = COMPILED diff --git a/third_party/protobuf/3.6.0/js/commonjs/export_testdeps.js b/third_party/protobuf/3.6.0/js/commonjs/export_testdeps.js new file mode 100644 index 0000000000..96d3f3470b --- /dev/null +++ b/third_party/protobuf/3.6.0/js/commonjs/export_testdeps.js @@ -0,0 +1,24 @@ +/** + * @fileoverview Export symbols needed by tests in CommonJS style. + * + * This file is like export.js, but for symbols that are only used by tests. + * However we exclude assert functions here, because they are exported into + * the global namespace, so those are handled as a special case in + * export_asserts.js. + */ + +// Include a dummy provide statement so that closurebuilder.py does not skip over this +// file. +goog.provide('jspb.ExportTestDeps'); + +goog.require('goog.crypt.base64'); +goog.require('goog.testing.PropertyReplacer'); +goog.require('jspb.arith.Int64'); +goog.require('jspb.arith.UInt64'); +goog.require('jspb.BinaryEncoder'); +goog.require('jspb.BinaryDecoder'); +goog.require('jspb.BinaryWriter'); +goog.require('jspb.utils'); + +exports.goog = goog; +exports.jspb = jspb; diff --git a/third_party/protobuf/3.6.0/js/commonjs/import_test.js b/third_party/protobuf/3.6.0/js/commonjs/import_test.js new file mode 100644 index 0000000000..ffa34fea61 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/commonjs/import_test.js @@ -0,0 +1,52 @@ +// 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. + +// Test suite is written using Jasmine -- see http://jasmine.github.io/ + + + +var googleProtobuf = require('google-protobuf'); +var asserts = require('closure_asserts_commonjs'); +var global = Function('return this')(); + +// Bring asserts into the global namespace. +googleProtobuf.object.extend(global, asserts); +googleProtobuf.exportSymbol('jspb.Message', googleProtobuf.Message, global); + +var test7_pb = require('./test7/test7_pb'); +googleProtobuf.exportSymbol('proto.jspb.test.framing.FramingMessage', test7_pb.FramingMessage, global); + +describe('Import test suite', function() { + it('testImportedMessage', function() { + var framing1 = new proto.jspb.test.framing.FramingMessage([]); + var framing2 = new proto.jspb.test.framing.FramingMessage([]); + assertObjectEquals(framing1.toObject(), framing2.toObject()); + }); +}); diff --git a/third_party/protobuf/3.6.0/js/commonjs/jasmine.json b/third_party/protobuf/3.6.0/js/commonjs/jasmine.json new file mode 100644 index 0000000000..666b8edbf8 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/commonjs/jasmine.json @@ -0,0 +1,9 @@ +{ + "spec_dir": "", + "spec_files": [ + "*_test.js", + "binary/proto_test.js" + ], + "helpers": [ + ] +} diff --git a/third_party/protobuf/3.6.0/js/commonjs/rewrite_tests_for_commonjs.js b/third_party/protobuf/3.6.0/js/commonjs/rewrite_tests_for_commonjs.js new file mode 100644 index 0000000000..b6d90d287d --- /dev/null +++ b/third_party/protobuf/3.6.0/js/commonjs/rewrite_tests_for_commonjs.js @@ -0,0 +1,97 @@ +/** + * @fileoverview Utility to translate test files to CommonJS imports. + * + * This is a somewhat hacky tool designed to do one very specific thing. + * All of the test files in *_test.js are written with Closure-style + * imports (goog.require()). This works great for running the tests + * against Closure-style generated code, but we also want to run the + * tests against CommonJS-style generated code without having to fork + * the tests. + * + * Closure-style imports import each individual type by name. This is + * very different than CommonJS imports which are by file. So we put + * special comments in these tests like: + * + * // CommonJS-LoadFromFile: test_pb + * goog.require('proto.jspb.test.CloneExtension'); + * goog.require('proto.jspb.test.Complex'); + * goog.require('proto.jspb.test.DefaultValues'); + * + * This script parses that special comment and uses it to generate proper + * CommonJS require() statements so that the tests can run and pass using + * CommonJS imports. The script will change the above statements into: + * + * var test_pb = require('test_pb'); + * googleProtobuf.exportSymbol('proto.jspb.test.CloneExtension', test_pb.CloneExtension, global); + * googleProtobuf.exportSymbol('proto.jspb.test.Complex', test_pb.Complex, global); + * googleProtobuf.exportSymbol('proto.jspb.test.DefaultValues', test_pb.DefaultValues, global); + * + * (The "exportSymbol" function will define the given names in the global + * namespace, taking care not to overwrite any previous value for + * "proto.jspb.test"). + */ + +var lineReader = require('readline').createInterface({ + input: process.stdin, + output: process.stdout +}); + +function tryStripPrefix(str, prefix) { + if (str.lastIndexOf(prefix) !== 0) { + throw "String: " + str + " didn't start with: " + prefix; + } + return str.substr(prefix.length); +} + +function camelCase(str) { + var ret = ''; + var ucaseNext = false; + for (var i = 0; i < str.length; i++) { + if (str[i] == '-') { + ucaseNext = true; + } else if (ucaseNext) { + ret += str[i].toUpperCase(); + ucaseNext = false; + } else { + ret += str[i]; + } + } + return ret; +} + +var module = null; +var pkg = null; + +// Header: goes in every file at the top. +console.log("var global = Function('return this')();"); +console.log("var googleProtobuf = require('google-protobuf');"); +console.log("var testdeps = require('testdeps_commonjs');"); +console.log("global.goog = testdeps.goog;"); +console.log("global.jspb = testdeps.jspb;"); +console.log("var asserts = require('closure_asserts_commonjs');"); +console.log(""); +console.log("// Bring asserts into the global namespace."); +console.log("googleProtobuf.object.extend(global, asserts);"); + +lineReader.on('line', function(line) { + var isRequire = line.match(/goog\.require\('([^']*)'\)/); + var isLoadFromFile = line.match(/CommonJS-LoadFromFile: (\S*) (.*)/); + var isSetTestOnly = line.match(/goog.setTestOnly()/); + if (isRequire) { + if (module) { // Skip goog.require() lines before the first directive. + var fullSym = isRequire[1]; + var sym = tryStripPrefix(fullSym, pkg); + console.log("googleProtobuf.exportSymbol('" + fullSym + "', " + module + sym + ', global);'); + } + } else if (isLoadFromFile) { + var module_path = isLoadFromFile[1].split('/'); + module = camelCase(module_path[module_path.length - 1]); + pkg = isLoadFromFile[2]; + + if (module != "googleProtobuf") { // We unconditionally require this in the header. + console.log("var " + module + " = require('./" + isLoadFromFile[1] + "');"); + } + } else if (!isSetTestOnly) { // Remove goog.setTestOnly() lines. + console.log(line); + } +}); diff --git a/third_party/protobuf/3.6.0/js/commonjs/test6/test6.proto b/third_party/protobuf/3.6.0/js/commonjs/test6/test6.proto new file mode 100644 index 0000000000..a060925f2d --- /dev/null +++ b/third_party/protobuf/3.6.0/js/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/third_party/protobuf/3.6.0/js/commonjs/test7/test7.proto b/third_party/protobuf/3.6.0/js/commonjs/test7/test7.proto new file mode 100644 index 0000000000..f5574a3dd3 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/binary/arith_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/binary/arith_test.js new file mode 100644 index 0000000000..89796bf795 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/binary/decoder_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/binary/decoder_test.js new file mode 100644 index 0000000000..fce2fe181c --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/binary/decoder_test.js @@ -0,0 +1,317 @@ +// 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()}); + decoder.reset(); + 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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/binary/proto_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/binary/proto_test.js new file mode 100644 index 0000000000..14d0f42e95 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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(null); + 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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/binary/reader_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/binary/reader_test.js new file mode 100644 index 0000000000..957113859e --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/binary/utils_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/binary/utils_test.js new file mode 100644 index 0000000000..d27e5ea2c6 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/binary/writer_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/binary/writer_test.js new file mode 100644 index 0000000000..d5dadb4135 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/export_asserts.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/export_asserts.js new file mode 100644 index 0000000000..5219d120c1 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/export_asserts.js @@ -0,0 +1,37 @@ +/** + * @fileoverview Exports symbols needed only by tests. + * + * This file exports several Closure Library symbols that are only + * used by tests. It is used to generate a file + * closure_asserts_commonjs.js that is only used at testing time. + */ + +goog.require('goog.testing.asserts'); + +var global = Function('return this')(); + +// All of the closure "assert" functions are exported at the global level. +// +// The Google Closure assert functions start with assert, eg. +// assertThrows +// assertNotThrows +// assertTrue +// ... +// +// The one exception is the "fail" function. +function shouldExport(str) { + return str.lastIndexOf('assert') === 0 || str == 'fail'; +} + +for (var key in global) { + if ((typeof key == "string") && global.hasOwnProperty(key) && + shouldExport(key)) { + exports[key] = global[key]; + } +} + +// The COMPILED variable is set by Closure compiler to "true" when it compiles +// JavaScript, so in practice this is equivalent to "exports.COMPILED = true". +// This will disable some debugging functionality in debug.js. We could +// investigate whether this can/should be enabled in CommonJS builds. +exports.COMPILED = COMPILED diff --git a/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/export_testdeps.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/export_testdeps.js new file mode 100644 index 0000000000..59c77ca2cd --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/export_testdeps.js @@ -0,0 +1,18 @@ +/** + * @fileoverview Export symbols needed by tests in CommonJS style. + * + * This file is like export.js, but for symbols that are only used by tests. + * However we exclude assert functions here, because they are exported into + * the global namespace, so those are handled as a special case in + * export_asserts.js. + */ + +goog.require('goog.crypt.base64'); +goog.require('jspb.arith.Int64'); +goog.require('jspb.arith.UInt64'); +goog.require('jspb.BinaryEncoder'); +goog.require('jspb.BinaryDecoder'); +goog.require('jspb.utils'); + +exports.goog = goog; +exports.jspb = jspb; diff --git a/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/import_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/import_test.js new file mode 100644 index 0000000000..ffa34fea61 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/import_test.js @@ -0,0 +1,52 @@ +// 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. + +// Test suite is written using Jasmine -- see http://jasmine.github.io/ + + + +var googleProtobuf = require('google-protobuf'); +var asserts = require('closure_asserts_commonjs'); +var global = Function('return this')(); + +// Bring asserts into the global namespace. +googleProtobuf.object.extend(global, asserts); +googleProtobuf.exportSymbol('jspb.Message', googleProtobuf.Message, global); + +var test7_pb = require('./test7/test7_pb'); +googleProtobuf.exportSymbol('proto.jspb.test.framing.FramingMessage', test7_pb.FramingMessage, global); + +describe('Import test suite', function() { + it('testImportedMessage', function() { + var framing1 = new proto.jspb.test.framing.FramingMessage([]); + var framing2 = new proto.jspb.test.framing.FramingMessage([]); + assertObjectEquals(framing1.toObject(), framing2.toObject()); + }); +}); diff --git a/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/jasmine.json b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/jasmine.json new file mode 100644 index 0000000000..666b8edbf8 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/jasmine.json @@ -0,0 +1,9 @@ +{ + "spec_dir": "", + "spec_files": [ + "*_test.js", + "binary/proto_test.js" + ], + "helpers": [ + ] +} diff --git a/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/rewrite_tests_for_commonjs.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/rewrite_tests_for_commonjs.js new file mode 100644 index 0000000000..b6d90d287d --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/rewrite_tests_for_commonjs.js @@ -0,0 +1,97 @@ +/** + * @fileoverview Utility to translate test files to CommonJS imports. + * + * This is a somewhat hacky tool designed to do one very specific thing. + * All of the test files in *_test.js are written with Closure-style + * imports (goog.require()). This works great for running the tests + * against Closure-style generated code, but we also want to run the + * tests against CommonJS-style generated code without having to fork + * the tests. + * + * Closure-style imports import each individual type by name. This is + * very different than CommonJS imports which are by file. So we put + * special comments in these tests like: + * + * // CommonJS-LoadFromFile: test_pb + * goog.require('proto.jspb.test.CloneExtension'); + * goog.require('proto.jspb.test.Complex'); + * goog.require('proto.jspb.test.DefaultValues'); + * + * This script parses that special comment and uses it to generate proper + * CommonJS require() statements so that the tests can run and pass using + * CommonJS imports. The script will change the above statements into: + * + * var test_pb = require('test_pb'); + * googleProtobuf.exportSymbol('proto.jspb.test.CloneExtension', test_pb.CloneExtension, global); + * googleProtobuf.exportSymbol('proto.jspb.test.Complex', test_pb.Complex, global); + * googleProtobuf.exportSymbol('proto.jspb.test.DefaultValues', test_pb.DefaultValues, global); + * + * (The "exportSymbol" function will define the given names in the global + * namespace, taking care not to overwrite any previous value for + * "proto.jspb.test"). + */ + +var lineReader = require('readline').createInterface({ + input: process.stdin, + output: process.stdout +}); + +function tryStripPrefix(str, prefix) { + if (str.lastIndexOf(prefix) !== 0) { + throw "String: " + str + " didn't start with: " + prefix; + } + return str.substr(prefix.length); +} + +function camelCase(str) { + var ret = ''; + var ucaseNext = false; + for (var i = 0; i < str.length; i++) { + if (str[i] == '-') { + ucaseNext = true; + } else if (ucaseNext) { + ret += str[i].toUpperCase(); + ucaseNext = false; + } else { + ret += str[i]; + } + } + return ret; +} + +var module = null; +var pkg = null; + +// Header: goes in every file at the top. +console.log("var global = Function('return this')();"); +console.log("var googleProtobuf = require('google-protobuf');"); +console.log("var testdeps = require('testdeps_commonjs');"); +console.log("global.goog = testdeps.goog;"); +console.log("global.jspb = testdeps.jspb;"); +console.log("var asserts = require('closure_asserts_commonjs');"); +console.log(""); +console.log("// Bring asserts into the global namespace."); +console.log("googleProtobuf.object.extend(global, asserts);"); + +lineReader.on('line', function(line) { + var isRequire = line.match(/goog\.require\('([^']*)'\)/); + var isLoadFromFile = line.match(/CommonJS-LoadFromFile: (\S*) (.*)/); + var isSetTestOnly = line.match(/goog.setTestOnly()/); + if (isRequire) { + if (module) { // Skip goog.require() lines before the first directive. + var fullSym = isRequire[1]; + var sym = tryStripPrefix(fullSym, pkg); + console.log("googleProtobuf.exportSymbol('" + fullSym + "', " + module + sym + ', global);'); + } + } else if (isLoadFromFile) { + var module_path = isLoadFromFile[1].split('/'); + module = camelCase(module_path[module_path.length - 1]); + pkg = isLoadFromFile[2]; + + if (module != "googleProtobuf") { // We unconditionally require this in the header. + console.log("var " + module + " = require('./" + isLoadFromFile[1] + "');"); + } + } else if (!isSetTestOnly) { // Remove goog.setTestOnly() lines. + console.log(line); + } +}); diff --git a/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/test6/test6.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/test6/test6.proto new file mode 100644 index 0000000000..a060925f2d --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/test7/test7.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/commonjs/test7/test7.proto new file mode 100644 index 0000000000..f5574a3dd3 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/data.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/data.proto new file mode 100644 index 0000000000..74a8a994c7 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/debug_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/debug_test.js new file mode 100644 index 0000000000..01cbf891ab --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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.setAString(undefined); + + 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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/jasmine1.json b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/jasmine1.json new file mode 100644 index 0000000000..6653c01cc7 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/jasmine1.json @@ -0,0 +1,17 @@ +{ + "spec_dir": "", + "spec_files": [ + "*_test.js", + "binary/*_test.js" + ], + "helpers": [ + "../../../js/node_modules/google-closure-library/closure/goog/bootstrap/nodejs.js", + "../../../js/node_loader.js", + "../../../js/deps.js", + "../../../js/google/protobuf/any.js", + "../../../js/google/protobuf/struct.js", + "../../../js/google/protobuf/timestamp.js", + "testproto_libs1.js", + "testproto_libs2.js" + ] +} diff --git a/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/jasmine2.json b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/jasmine2.json new file mode 100644 index 0000000000..3208078f7e --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/jasmine2.json @@ -0,0 +1,17 @@ +{ + "spec_dir": "", + "spec_files": [ + "*_test.js", + "binary/*_test.js" + ], + "helpers": [ + "../../../js/node_modules/google-closure-library/closure/goog/bootstrap/nodejs.js", + "../../../js/node_loader.js", + "../../../js/deps.js", + "../../../js/google/protobuf/any.js", + "../../../js/google/protobuf/struct.js", + "../../../js/google/protobuf/timestamp.js", + "testproto_libs1_new.js", + "testproto_libs2.js" + ] +} diff --git a/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/jasmine3.json b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/jasmine3.json new file mode 100644 index 0000000000..3fb9a1b01d --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/jasmine3.json @@ -0,0 +1,17 @@ +{ + "spec_dir": "", + "spec_files": [ + "*_test.js", + "binary/*_test.js" + ], + "helpers": [ + "../../../js/node_modules/google-closure-library/closure/goog/bootstrap/nodejs.js", + "../../../js/node_loader.js", + "../../../js/deps.js", + "../../../js/google/protobuf/any.js", + "../../../js/google/protobuf/struct.js", + "../../../js/google/protobuf/timestamp.js", + "testproto_libs1.js", + "testproto_libs2_new.js" + ] +} diff --git a/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/message_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/message_test.js new file mode 100644 index 0000000000..b779143115 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/message_test.js @@ -0,0 +1,1080 @@ +// 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('testMessageRegistration', 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); + 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()); + + // Test set(null). We could deprecated this in favor of clear(), but + // it's also convenient to have. + data = ['str', true, [11], [[22], [33]], ['s1', 's2']]; + foo = new proto.jspb.test.OptionalFields(data); + foo.setAString(null); + foo.setABool(null); + foo.setANestedMessage(null); + foo.setARepeatedMessageList(null); + foo.setARepeatedStringList(null); + assertEquals('', foo.getAString()); + assertEquals(false, foo.getABool()); + assertNull(foo.getANestedMessage()); + assertFalse(foo.hasAString()); + assertFalse(foo.hasABool()); + assertObjectEquals([], foo.getARepeatedMessageList()); + assertObjectEquals([], foo.getARepeatedStringList()); + assertObjectEquals([null, null, null, [], []], foo.toArray()); + + // Test set(undefined). Again, not something we really need, and not + // supported directly by our typing, but it should 'do the right thing'. + data = ['str', true, [11], [[22], [33]], ['s1', 's2']]; + foo = new proto.jspb.test.OptionalFields(data); + foo.setAString(undefined); + foo.setABool(undefined); + foo.setANestedMessage(undefined); + foo.setARepeatedMessageList(undefined); + foo.setARepeatedStringList(undefined); + assertEquals('', foo.getAString()); + assertEquals(false, foo.getABool()); + assertUndefined(foo.getANestedMessage()); + assertFalse(foo.hasAString()); + assertFalse(foo.hasABool()); + assertObjectEquals([], foo.getARepeatedMessageList()); + assertObjectEquals([], foo.getARepeatedStringList()); + expected = [,,, [], []]; + expected[0] = expected[1] = expected[2] = undefined; + assertObjectEquals(expected, foo.toArray()); + }); + + it('testDifferenceRawObject', 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.cloneMessage(); + 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', 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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/proto3_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/proto3_test.js new file mode 100644 index 0000000000..fab0fd44ff --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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.setOneofUint32(null); + + + 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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/proto3_test.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/proto3_test.proto new file mode 100644 index 0000000000..acb6716492 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/test.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/test.proto new file mode 100644 index 0000000000..937ffb89ce --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/test.proto @@ -0,0 +1,236 @@ +// 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; +} + diff --git a/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/test.sh b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/test.sh new file mode 100644 index 0000000000..9d58f30ac3 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/test.sh @@ -0,0 +1,92 @@ +#!/bin/bash + +set -e + +# Download protoc 3.0.0 from Maven if it is not already present. +OLD_PROTOC_URL=https://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0/protoc-3.0.0-linux-x86_64.exe +if [ ! -f protoc ]; then + wget $OLD_PROTOC_URL -O protoc + chmod +x protoc +fi + +pushd ../.. +npm install && npm test +popd + +old_protoc=./protoc +new_protoc=../../../src/protoc + +# The protos in group 2 have some dependencies on protos in group 1. The tests +# will verify that the generated code for one group can be regenerated +# independently of the other group in a compatible way. +# +# Note: these lists of protos duplicate the lists in gulpfile.js. Ideally we +# should find a good way of having a single source of truth for this. +group1_protos="data.proto test3.proto test5.proto commonjs/test6/test6.proto testbinary.proto testempty.proto test.proto" +group2_protos="proto3_test.proto test2.proto test4.proto commonjs/test7/test7.proto" + +# We test the following cases: +# +# Case 1: build groups 1 and 2 with the old protoc +# Case 2: build group 1 with new protoc but group 2 with old protoc +# Case 3: build group 1 with old protoc but group 2 with new protoc +# +# In each case, we use the current runtime. + +# +# CommonJS tests +# +mkdir -p commonjs_out{1,2,3} +# Case 1 +$old_protoc --js_out=import_style=commonjs,binary:commonjs_out1 -I ../../../src -I commonjs -I . $group1_protos +$old_protoc --js_out=import_style=commonjs,binary:commonjs_out1 -I ../../../src -I commonjs -I . $group2_protos +# Case 2 +$new_protoc --js_out=import_style=commonjs,binary:commonjs_out2 -I ../../../src -I commonjs -I . $group1_protos +$old_protoc --js_out=import_style=commonjs,binary:commonjs_out2 -I ../../../src -I commonjs -I . $group2_protos +# Case 3 +$old_protoc --js_out=import_style=commonjs,binary:commonjs_out3 -I ../../../src -I commonjs -I . $group1_protos +$new_protoc --js_out=import_style=commonjs,binary:commonjs_out3 -I ../../../src -I commonjs -I . $group2_protos + +mkdir -p commonjs_out/binary +for file in *_test.js binary/*_test.js; do + node commonjs/rewrite_tests_for_commonjs.js < "$file" > "commonjs_out/$file" +done +cp commonjs/{jasmine.json,import_test.js} commonjs_out/ +mkdir -p commonjs_out/test_node_modules +../../node_modules/google-closure-library/closure/bin/calcdeps.py -i commonjs/export_asserts.js -p . -p ../../node_modules/google-closure-library/closure -o compiled --compiler_jar ../../node_modules/google-closure-compiler/compiler.jar > commonjs_out/test_node_modules/closure_asserts_commonjs.js +../../node_modules/google-closure-library/closure/bin/calcdeps.py -i commonjs/export_testdeps.js -p ../.. -p ../../node_modules/google-closure-library/closure -o compiled --compiler_jar ../../node_modules/google-closure-compiler/compiler.jar > commonjs_out/test_node_modules/testdeps_commonjs.js +cp ../../google-protobuf.js commonjs_out/test_node_modules +cp -r ../../commonjs_out/node_modules commonjs_out + +echo +echo "Running tests with CommonJS imports" +echo "-----------------------------------" +for i in 1 2 3; do + cp -r commonjs_out/* "commonjs_out$i" + pushd "commonjs_out$i" + JASMINE_CONFIG_PATH=jasmine.json NODE_PATH=test_node_modules ../../../node_modules/.bin/jasmine + popd +done + +# +# Closure tests +# +$old_protoc --js_out=library=testproto_libs1,binary:. -I ../../../src -I commonjs -I . $group1_protos +$old_protoc --js_out=library=testproto_libs2,binary:. -I ../../../src -I commonjs -I . $group2_protos +$new_protoc --js_out=library=testproto_libs1_new,binary:. -I ../../../src -I commonjs -I . $group1_protos +$new_protoc --js_out=library=testproto_libs2_new,binary:. -I ../../../src -I commonjs -I . $group2_protos + +echo +echo "Running tests with Closure-style imports" +echo "----------------------------------------" + +# Case 1 +JASMINE_CONFIG_PATH=jasmine1.json ../../node_modules/.bin/jasmine +# Case 2 +JASMINE_CONFIG_PATH=jasmine2.json ../../node_modules/.bin/jasmine +# Case 3 +JASMINE_CONFIG_PATH=jasmine3.json ../../node_modules/.bin/jasmine + +# Remove these files so that calcdeps.py does not get confused by them the next +# time this script runs. +rm testproto_libs[12]* diff --git a/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/test2.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/test2.proto new file mode 100644 index 0000000000..44e55effcb --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/test3.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/test3.proto new file mode 100644 index 0000000000..940a552ed5 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/test4.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/test4.proto new file mode 100644 index 0000000000..cf2451e9cb --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/test5.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/test5.proto new file mode 100644 index 0000000000..34979517e5 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/testbinary.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/testbinary.proto new file mode 100644 index 0000000000..116f17fb50 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/testempty.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.0/testempty.proto new file mode 100644 index 0000000000..960bce4e5c --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.0.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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/binary/arith_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/binary/arith_test.js new file mode 100644 index 0000000000..89796bf795 --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/binary/decoder_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/binary/decoder_test.js new file mode 100644 index 0000000000..fce2fe181c --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/binary/decoder_test.js @@ -0,0 +1,317 @@ +// 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()}); + decoder.reset(); + 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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/binary/proto_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/binary/proto_test.js new file mode 100644 index 0000000000..26e1d30f1c --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/binary/reader_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/binary/reader_test.js new file mode 100644 index 0000000000..957113859e --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/binary/utils_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/binary/utils_test.js new file mode 100644 index 0000000000..d27e5ea2c6 --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/binary/writer_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/binary/writer_test.js new file mode 100644 index 0000000000..d5dadb4135 --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/commonjs/test6/test6.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/commonjs/test6/test6.proto new file mode 100644 index 0000000000..a060925f2d --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/commonjs/test7/test7.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/commonjs/test7/test7.proto new file mode 100644 index 0000000000..f5574a3dd3 --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/data.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/data.proto new file mode 100644 index 0000000000..74a8a994c7 --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/debug_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/debug_test.js new file mode 100644 index 0000000000..702cc76e90 --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/maps_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/maps_test.js new file mode 100644 index 0000000000..0d442f4fd1 --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/message_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/message_test.js new file mode 100644 index 0000000000..c1023784fa --- /dev/null +++ b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/message_test.js @@ -0,0 +1,1032 @@ +// 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([]); + 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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/proto3_test.js b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/proto3_test.js new file mode 100644 index 0000000000..3c929effd5 --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/proto3_test.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/proto3_test.proto new file mode 100644 index 0000000000..acb6716492 --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/test.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/test.proto new file mode 100644 index 0000000000..48cb37e112 --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/test2.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/test2.proto new file mode 100644 index 0000000000..44e55effcb --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/test3.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/test3.proto new file mode 100644 index 0000000000..940a552ed5 --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/test4.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/test4.proto new file mode 100644 index 0000000000..cf2451e9cb --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/test5.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/test5.proto new file mode 100644 index 0000000000..34979517e5 --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/testbinary.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/testbinary.proto new file mode 100644 index 0000000000..116f17fb50 --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/testempty.proto b/third_party/protobuf/3.6.0/js/compatibility_tests/v3.1.0/testempty.proto new file mode 100644 index 0000000000..960bce4e5c --- /dev/null +++ b/third_party/protobuf/3.6.0/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/third_party/protobuf/3.6.0/js/data.proto b/third_party/protobuf/3.6.0/js/data.proto new file mode 100644 index 0000000000..74a8a994c7 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/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/third_party/protobuf/3.6.0/js/debug.js b/third_party/protobuf/3.6.0/js/debug.js new file mode 100644 index 0000000000..ba51bbe01c --- /dev/null +++ b/third_party/protobuf/3.6.0/js/debug.js @@ -0,0 +1,148 @@ +// 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 Utilities to debug JSPB based proto objects. + */ + +goog.provide('jspb.debug'); + +goog.require('goog.array'); +goog.require('goog.asserts'); +goog.require('goog.object'); +goog.require('jspb.Message'); + + +/** + * Turns a proto into a human readable object that can i.e. be written to the + * console: `console.log(jspb.debug.dump(myProto))`. + * This function makes a best effort and may not work in all cases. It will not + * work in obfuscated and or optimized code. + * Use this in environments where {@see jspb.Message.prototype.toObject} is + * not available for code size reasons. + * @param {jspb.Message} message A jspb.Message. + * @return {Object} + */ +jspb.debug.dump = function(message) { + if (!goog.DEBUG) { + return null; + } + goog.asserts.assert(message instanceof jspb.Message, + 'jspb.Message instance expected'); + /** @type {Object} */ + var object = message; + goog.asserts.assert(object['getExtension'], + 'Only unobfuscated and unoptimized compilation modes supported.'); + return /** @type {Object} */ (jspb.debug.dump_(message)); +}; + + +/** + * Recursively introspects a message and the values its getters return to + * make a best effort in creating a human readable representation of the + * message. + * @param {?} thing A jspb.Message, Array or primitive type to dump. + * @return {*} + * @private + */ +jspb.debug.dump_ = function(thing) { + var type = goog.typeOf(thing); + var message = thing; // Copy because we don't want type inference on thing. + if (type == 'number' || type == 'string' || type == 'boolean' || + type == 'null' || type == 'undefined') { + return thing; + } + if (typeof Uint8Array !== 'undefined') { + // Will fail on IE9, where Uint8Array doesn't exist. + if (message instanceof Uint8Array) { + return thing; + } + } + + if (type == 'array') { + goog.asserts.assertArray(thing); + return goog.array.map(thing, jspb.debug.dump_); + } + goog.asserts.assert(message instanceof jspb.Message, + 'Only messages expected: ' + thing); + var ctor = message.constructor; + var messageName = ctor.name || ctor.displayName; + var object = { + '$name': messageName + }; + for (var name in ctor.prototype) { + var match = /^get([A-Z]\w*)/.exec(name); + if (match && name != 'getExtension' && + name != 'getJsPbMessageId') { + var has = 'has' + match[1]; + if (!thing[has] || thing[has]()) { + var val = thing[name](); + object[jspb.debug.formatFieldName_(match[1])] = jspb.debug.dump_(val); + } + } + } + if (COMPILED && thing['extensionObject_']) { + object['$extensions'] = 'Recursive dumping of extensions not supported ' + + 'in compiled code. Switch to uncompiled or dump extension object ' + + 'directly'; + return object; + } + var extensionsObject; + for (var id in ctor['extensions']) { + if (/^\d+$/.test(id)) { + var ext = ctor['extensions'][id]; + var extVal = thing.getExtension(ext); + var fieldName = goog.object.getKeys(ext.fieldName)[0]; + if (extVal != null) { + if (!extensionsObject) { + extensionsObject = object['$extensions'] = {}; + } + extensionsObject[jspb.debug.formatFieldName_(fieldName)] = + jspb.debug.dump_(extVal); + } + } + } + return object; +}; + + +/** + * Formats a field name for output as camelCase. + * + * @param {string} name Name of the field. + * @return {string} + * @private + */ +jspb.debug.formatFieldName_ = function(name) { + // Name may be in TitleCase. + return name.replace(/^[A-Z]/, function(c) { + return c.toLowerCase(); + }); +}; diff --git a/third_party/protobuf/3.6.0/js/debug_test.js b/third_party/protobuf/3.6.0/js/debug_test.js new file mode 100644 index 0000000000..d0d646a5f8 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/debug_test.js @@ -0,0 +1,116 @@ +// 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'); + + +// CommonJS-LoadFromFile: testbinary_pb +goog.require('proto.jspb.test.TestAllTypes'); + +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('testBytes', function() { + if (COMPILED || typeof Uint8Array == 'undefined') { + return; + } + var message = new proto.jspb.test.TestAllTypes(); + var bytes = new Uint8Array(4); + message.setOptionalBytes(bytes); + assertEquals(jspb.debug.dump(message)['optionalBytes'], bytes); + }); + + 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/third_party/protobuf/3.6.0/js/gulpfile.js b/third_party/protobuf/3.6.0/js/gulpfile.js new file mode 100644 index 0000000000..fc9559f934 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/gulpfile.js @@ -0,0 +1,214 @@ +var gulp = require('gulp'); +var execFile = require('child_process').execFile; +var glob = require('glob'); + +function exec(command, cb) { + execFile('sh', ['-c', command], cb); +} + +var protoc = process.env.PROTOC || '../src/protoc'; + +var wellKnownTypes = [ + '../src/google/protobuf/any.proto', + '../src/google/protobuf/api.proto', + '../src/google/protobuf/compiler/plugin.proto', + '../src/google/protobuf/descriptor.proto', + '../src/google/protobuf/duration.proto', + '../src/google/protobuf/empty.proto', + '../src/google/protobuf/field_mask.proto', + '../src/google/protobuf/source_context.proto', + '../src/google/protobuf/struct.proto', + '../src/google/protobuf/timestamp.proto', + '../src/google/protobuf/type.proto', + '../src/google/protobuf/wrappers.proto', +]; + +var group1Protos = [ + 'data.proto', + 'test3.proto', + 'test5.proto', + 'commonjs/test6/test6.proto', + 'test8.proto', + 'testbinary.proto', + 'testempty.proto', + 'test.proto', +]; + +var group2Protos = [ + 'proto3_test.proto', + 'test2.proto', + 'test4.proto', + 'commonjs/test7/test7.proto', +]; + +gulp.task('genproto_well_known_types_closure', function (cb) { + exec(protoc + ' --js_out=one_output_file_per_input_file,binary:. -I ../src -I . ' + wellKnownTypes.join(' '), + function (err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); +}); + +gulp.task('genproto_group1_closure', function (cb) { + exec(protoc + ' --js_out=library=testproto_libs1,binary:. -I ../src -I . ' + group1Protos.join(' '), + function (err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); +}); + +gulp.task('genproto_group2_closure', function (cb) { + exec(protoc + ' --js_out=library=testproto_libs2,binary:. -I ../src -I . -I commonjs ' + group2Protos.join(' '), + function (err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); +}); + +gulp.task('genproto_well_known_types_commonjs', function (cb) { + exec('mkdir -p commonjs_out && ' + protoc + ' --js_out=import_style=commonjs,binary:commonjs_out -I ../src ' + wellKnownTypes.join(' '), + function (err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); +}); + +gulp.task('genproto_group1_commonjs', function (cb) { + exec('mkdir -p commonjs_out && ' + protoc + ' --js_out=import_style=commonjs,binary:commonjs_out -I ../src -I commonjs -I . ' + group1Protos.join(' '), + function (err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); +}); + +gulp.task('genproto_group2_commonjs', function (cb) { + exec('mkdir -p commonjs_out && ' + protoc + ' --js_out=import_style=commonjs,binary:commonjs_out -I ../src -I commonjs -I . ' + group2Protos.join(' '), + function (err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); +}); + +gulp.task('genproto_commonjs_wellknowntypes', function (cb) { + exec('mkdir -p commonjs_out/node_modules/google-protobuf && ' + protoc + ' --js_out=import_style=commonjs,binary:commonjs_out/node_modules/google-protobuf -I ../src ' + wellKnownTypes.join(' '), + function (err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); +}); + +gulp.task('genproto_wellknowntypes', function (cb) { + exec(protoc + ' --js_out=import_style=commonjs,binary:. -I ../src ' + wellKnownTypes.join(' '), + function (err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); +}); + +function getClosureBuilderCommand(exportsFile, outputFile) { + return './node_modules/google-closure-library/closure/bin/build/closurebuilder.py ' + + '--root node_modules ' + + '-o compiled ' + + '--compiler_jar node_modules/google-closure-compiler/compiler.jar ' + + '-i ' + exportsFile + ' ' + + 'map.js message.js binary/arith.js binary/constants.js binary/decoder.js ' + + 'binary/encoder.js binary/reader.js binary/utils.js binary/writer.js ' + + exportsFile + ' > ' + outputFile; +} + +gulp.task('dist', ['genproto_wellknowntypes'], function (cb) { + // TODO(haberman): minify this more aggressively. + // Will require proper externs/exports. + exec(getClosureBuilderCommand('commonjs/export.js', 'google-protobuf.js'), + function (err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); +}); + +gulp.task('commonjs_asserts', function (cb) { + exec('mkdir -p commonjs_out/test_node_modules && ' + + getClosureBuilderCommand( + 'commonjs/export_asserts.js', + 'commonjs_out/test_node_modules/closure_asserts_commonjs.js'), + function (err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); +}); + +gulp.task('commonjs_testdeps', function (cb) { + exec('mkdir -p commonjs_out/test_node_modules && ' + + getClosureBuilderCommand( + 'commonjs/export_testdeps.js', + 'commonjs_out/test_node_modules/testdeps_commonjs.js'), + function (err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); +}); + +gulp.task('make_commonjs_out', ['dist', 'genproto_well_known_types_commonjs', 'genproto_group1_commonjs', 'genproto_group2_commonjs', 'genproto_commonjs_wellknowntypes', 'commonjs_asserts', 'commonjs_testdeps'], function (cb) { + // TODO(haberman): minify this more aggressively. + // Will require proper externs/exports. + var cmd = "mkdir -p commonjs_out/binary && mkdir -p commonjs_out/test_node_modules && "; + function addTestFile(file) { + cmd += 'node commonjs/rewrite_tests_for_commonjs.js < ' + file + + ' > commonjs_out/' + file + '&& '; + } + + glob.sync('*_test.js').forEach(addTestFile); + glob.sync('binary/*_test.js').forEach(addTestFile); + + exec(cmd + + 'cp commonjs/jasmine.json commonjs_out/jasmine.json && ' + + 'cp google-protobuf.js commonjs_out/test_node_modules && ' + + 'cp commonjs/import_test.js commonjs_out/import_test.js', + function (err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); +}); + +gulp.task('deps', ['genproto_well_known_types_closure', 'genproto_group1_closure', 'genproto_group2_closure'], function (cb) { + exec('./node_modules/google-closure-library/closure/bin/build/depswriter.py binary/arith.js binary/constants.js binary/decoder.js binary/encoder.js binary/reader.js binary/utils.js binary/writer.js debug.js map.js message.js node_loader.js test_bootstrap.js > deps.js', + function (err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); +}); + +gulp.task('test_closure', ['genproto_well_known_types_closure', 'genproto_group1_closure', 'genproto_group2_closure', 'deps'], function (cb) { + exec('JASMINE_CONFIG_PATH=jasmine.json ./node_modules/.bin/jasmine', + function (err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); +}); + +gulp.task('test_commonjs', ['make_commonjs_out'], function (cb) { + exec('cd commonjs_out && JASMINE_CONFIG_PATH=jasmine.json NODE_PATH=test_node_modules ../node_modules/.bin/jasmine', + function (err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); +}); + +gulp.task('test', ['test_closure', 'test_commonjs'], function(cb) { + cb(); +}); diff --git a/third_party/protobuf/3.6.0/js/jasmine.json b/third_party/protobuf/3.6.0/js/jasmine.json new file mode 100644 index 0000000000..aeea72f857 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/jasmine.json @@ -0,0 +1,17 @@ +{ + "spec_dir": "", + "spec_files": [ + "*_test.js", + "binary/*_test.js" + ], + "helpers": [ + "node_modules/google-closure-library/closure/goog/bootstrap/nodejs.js", + "node_loader.js", + "deps.js", + "google/protobuf/any.js", + "google/protobuf/struct.js", + "google/protobuf/timestamp.js", + "testproto_libs1.js", + "testproto_libs2.js" + ] +} diff --git a/third_party/protobuf/3.6.0/js/map.js b/third_party/protobuf/3.6.0/js/map.js new file mode 100644 index 0000000000..2fb1483756 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/map.js @@ -0,0 +1,542 @@ +// 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.provide('jspb.Map'); + +goog.require('goog.asserts'); + +goog.forwardDeclare('jspb.BinaryReader'); +goog.forwardDeclare('jspb.BinaryWriter'); + + + +/** + * Constructs a new Map. A Map is a container that is used to implement map + * fields on message objects. It closely follows the ES6 Map API; however, + * it is distinct because we do not want to depend on external polyfills or + * on ES6 itself. + * + * This constructor should only be called from generated message code. It is not + * intended for general use by library consumers. + * + * @template K, V + * + * @param {!Array<!Array<?>>} arr + * + * @param {?function(new:V, ?=)=} opt_valueCtor + * The constructor for type V, if type V is a message type. + * + * @constructor + * @struct + */ +jspb.Map = function(arr, opt_valueCtor) { + /** @const @private */ + this.arr_ = arr; + /** @const @private */ + this.valueCtor_ = opt_valueCtor; + + /** @type {!Object<string, !jspb.Map.Entry_<K,V>>} @private */ + this.map_ = {}; + + /** + * Is `this.arr_ updated with respect to `this.map_`? + * @type {boolean} + */ + this.arrClean = true; + + if (this.arr_.length > 0) { + this.loadFromArray_(); + } +}; + + +/** + * Load initial content from underlying array. + * @private + */ +jspb.Map.prototype.loadFromArray_ = function() { + for (var i = 0; i < this.arr_.length; i++) { + var record = this.arr_[i]; + var key = record[0]; + var value = record[1]; + this.map_[key.toString()] = new jspb.Map.Entry_(key, value); + } + this.arrClean = true; +}; + + +/** + * Synchronize content to underlying array, if needed, and return it. + * @return {!Array<!Array<!Object>>} + */ +jspb.Map.prototype.toArray = function() { + if (this.arrClean) { + if (this.valueCtor_) { + // We need to recursively sync maps in submessages to their arrays. + var m = this.map_; + for (var p in m) { + if (Object.prototype.hasOwnProperty.call(m, p)) { + var valueWrapper = /** @type {?jspb.Message} */ (m[p].valueWrapper); + if (valueWrapper) { + valueWrapper.toArray(); + } + } + } + } + } else { + // Delete all elements. + this.arr_.length = 0; + var strKeys = this.stringKeys_(); + // Output keys in deterministic (sorted) order. + strKeys.sort(); + for (var i = 0; i < strKeys.length; i++) { + var entry = this.map_[strKeys[i]]; + var valueWrapper = /** @type {?jspb.Message} */ (entry.valueWrapper); + if (valueWrapper) { + valueWrapper.toArray(); + } + this.arr_.push([entry.key, entry.value]); + } + this.arrClean = true; + } + return this.arr_; +}; + + +/** + * Returns the map formatted as an array of key-value pairs, suitable for the + * toObject() form of a message. + * + * @param {boolean=} includeInstance Whether to include the JSPB instance for + * transitional soy proto support: http://goto/soy-param-migration + * @param {!function((boolean|undefined),V):!Object=} valueToObject + * The static toObject() method, if V is a message type. + * @return {!Array<!Array<!Object>>} + */ +jspb.Map.prototype.toObject = function(includeInstance, valueToObject) { + var rawArray = this.toArray(); + var entries = []; + for (var i = 0; i < rawArray.length; i++) { + var entry = this.map_[rawArray[i][0].toString()]; + this.wrapEntry_(entry); + var valueWrapper = /** @type {V|undefined} */ (entry.valueWrapper); + if (valueWrapper) { + goog.asserts.assert(valueToObject); + entries.push([entry.key, valueToObject(includeInstance, valueWrapper)]); + } else { + entries.push([entry.key, entry.value]); + } + } + return entries; +}; + + +/** + * Returns a Map from the given array of key-value pairs when the values are of + * message type. The values in the array must match the format returned by their + * message type's toObject() method. + * + * @template K, V + * @param {!Array<!Array<!Object>>} entries + * @param {!function(new:V,?=)} valueCtor + * The constructor for type V. + * @param {!function(!Object):V} valueFromObject + * The fromObject function for type V. + * @return {!jspb.Map<K, V>} + */ +jspb.Map.fromObject = function(entries, valueCtor, valueFromObject) { + var result = new jspb.Map([], valueCtor); + for (var i = 0; i < entries.length; i++) { + var key = entries[i][0]; + var value = valueFromObject(entries[i][1]); + result.set(key, value); + } + return result; +}; + + +/** + * Helper: an IteratorIterable over an array. + * @template T + * @param {!Array<T>} arr the array + * @implements {IteratorIterable<T>} + * @constructor @struct + * @private + */ +jspb.Map.ArrayIteratorIterable_ = function(arr) { + /** @type {number} @private */ + this.idx_ = 0; + + /** @const @private */ + this.arr_ = arr; +}; + + +/** @override @final */ +jspb.Map.ArrayIteratorIterable_.prototype.next = function() { + if (this.idx_ < this.arr_.length) { + return {done: false, value: this.arr_[this.idx_++]}; + } else { + return {done: true, value: undefined}; + } +}; + +if (typeof(Symbol) != 'undefined') { + /** @override */ + jspb.Map.ArrayIteratorIterable_.prototype[Symbol.iterator] = function() { + return this; + }; +} + + +/** + * Returns the map's length (number of key/value pairs). + * @return {number} + */ +jspb.Map.prototype.getLength = function() { + return this.stringKeys_().length; +}; + + +/** + * Clears the map. + */ +jspb.Map.prototype.clear = function() { + this.map_ = {}; + this.arrClean = false; +}; + + +/** + * Deletes a particular key from the map. + * N.B.: differs in name from ES6 Map's `delete` because IE8 does not support + * reserved words as property names. + * @this {jspb.Map} + * @param {K} key + * @return {boolean} Whether any entry with this key was deleted. + */ +jspb.Map.prototype.del = function(key) { + var keyValue = key.toString(); + var hadKey = this.map_.hasOwnProperty(keyValue); + delete this.map_[keyValue]; + this.arrClean = false; + return hadKey; +}; + + +/** + * Returns an array of [key, value] pairs in the map. + * + * This is redundant compared to the plain entries() method, but we provide this + * to help out Angular 1.x users. Still evaluating whether this is the best + * option. + * + * @return {!Array<!Array<K|V>>} + */ +jspb.Map.prototype.getEntryList = function() { + var entries = []; + var strKeys = this.stringKeys_(); + strKeys.sort(); + for (var i = 0; i < strKeys.length; i++) { + var entry = this.map_[strKeys[i]]; + entries.push([entry.key, entry.value]); + } + return entries; +}; + + +/** + * Returns an iterator-iterable over [key, value] pairs in the map. + * Closure compiler sadly doesn't support tuples, ie. Iterator<[K,V]>. + * @return {!IteratorIterable<!Array<K|V>>} The iterator-iterable. + */ +jspb.Map.prototype.entries = function() { + var entries = []; + var strKeys = this.stringKeys_(); + strKeys.sort(); + for (var i = 0; i < strKeys.length; i++) { + var entry = this.map_[strKeys[i]]; + entries.push([entry.key, this.wrapEntry_(entry)]); + } + return new jspb.Map.ArrayIteratorIterable_(entries); +}; + + +/** + * Returns an iterator-iterable over keys in the map. + * @return {!IteratorIterable<K>} The iterator-iterable. + */ +jspb.Map.prototype.keys = function() { + var keys = []; + var strKeys = this.stringKeys_(); + strKeys.sort(); + for (var i = 0; i < strKeys.length; i++) { + var entry = this.map_[strKeys[i]]; + keys.push(entry.key); + } + return new jspb.Map.ArrayIteratorIterable_(keys); +}; + + +/** + * Returns an iterator-iterable over values in the map. + * @return {!IteratorIterable<V>} The iterator-iterable. + */ +jspb.Map.prototype.values = function() { + var values = []; + var strKeys = this.stringKeys_(); + strKeys.sort(); + for (var i = 0; i < strKeys.length; i++) { + var entry = this.map_[strKeys[i]]; + values.push(this.wrapEntry_(entry)); + } + return new jspb.Map.ArrayIteratorIterable_(values); +}; + + +/** + * Iterates over entries in the map, calling a function on each. + * @template T + * @param {function(this:T, V, K, ?jspb.Map<K, V>)} cb + * @param {T=} opt_thisArg + */ +jspb.Map.prototype.forEach = function(cb, opt_thisArg) { + var strKeys = this.stringKeys_(); + strKeys.sort(); + for (var i = 0; i < strKeys.length; i++) { + var entry = this.map_[strKeys[i]]; + cb.call(opt_thisArg, this.wrapEntry_(entry), entry.key, this); + } +}; + + +/** + * Sets a key in the map to the given value. + * @param {K} key The key + * @param {V} value The value + * @return {!jspb.Map<K,V>} + */ +jspb.Map.prototype.set = function(key, value) { + var entry = new jspb.Map.Entry_(key); + if (this.valueCtor_) { + entry.valueWrapper = value; + // .toArray() on a message returns a reference to the underlying array + // rather than a copy. + entry.value = value.toArray(); + } else { + entry.value = value; + } + this.map_[key.toString()] = entry; + this.arrClean = false; + return this; +}; + + +/** + * Helper: lazily construct a wrapper around an entry, if needed, and return the + * user-visible type. + * @param {!jspb.Map.Entry_<K,V>} entry + * @return {V} + * @private + */ +jspb.Map.prototype.wrapEntry_ = function(entry) { + if (this.valueCtor_) { + if (!entry.valueWrapper) { + entry.valueWrapper = new this.valueCtor_(entry.value); + } + return /** @type {V} */ (entry.valueWrapper); + } else { + return entry.value; + } +}; + + +/** + * Gets the value corresponding to a key in the map. + * @param {K} key + * @return {V|undefined} The value, or `undefined` if key not present + */ +jspb.Map.prototype.get = function(key) { + var keyValue = key.toString(); + var entry = this.map_[keyValue]; + if (entry) { + return this.wrapEntry_(entry); + } else { + return undefined; + } +}; + + +/** + * Determines whether the given key is present in the map. + * @param {K} key + * @return {boolean} `true` if the key is present + */ +jspb.Map.prototype.has = function(key) { + var keyValue = key.toString(); + return (keyValue in this.map_); +}; + + +/** + * Write this Map field in wire format to a BinaryWriter, using the given field + * number. + * @param {number} fieldNumber + * @param {!jspb.BinaryWriter} writer + * @param {!function(this:jspb.BinaryWriter,number,K)} keyWriterFn + * The method on BinaryWriter that writes type K to the stream. + * @param {!function(this:jspb.BinaryWriter,number,V,?=)| + * function(this:jspb.BinaryWriter,number,V,?)} valueWriterFn + * The method on BinaryWriter that writes type V to the stream. May be + * writeMessage, in which case the second callback arg form is used. + * @param {function(V,!jspb.BinaryWriter)=} opt_valueWriterCallback + * The BinaryWriter serialization callback for type V, if V is a message + * type. + */ +jspb.Map.prototype.serializeBinary = function( + fieldNumber, writer, keyWriterFn, valueWriterFn, opt_valueWriterCallback) { + var strKeys = this.stringKeys_(); + strKeys.sort(); + for (var i = 0; i < strKeys.length; i++) { + var entry = this.map_[strKeys[i]]; + writer.beginSubMessage(fieldNumber); + keyWriterFn.call(writer, 1, entry.key); + if (this.valueCtor_) { + valueWriterFn.call(writer, 2, this.wrapEntry_(entry), + opt_valueWriterCallback); + } else { + /** @type {function(this:jspb.BinaryWriter,number,?)} */ (valueWriterFn) + .call(writer, 2, entry.value); + } + writer.endSubMessage(); + } +}; + + +/** + * Read one key/value message from the given BinaryReader. Compatible as the + * `reader` callback parameter to jspb.BinaryReader.readMessage, to be called + * when a key/value pair submessage is encountered. If the Key is undefined, + * we should default it to 0. + * @template K, V + * @param {!jspb.Map} map + * @param {!jspb.BinaryReader} reader + * @param {!function(this:jspb.BinaryReader):K} keyReaderFn + * The method on BinaryReader that reads type K from the stream. + * + * @param {!function(this:jspb.BinaryReader):V| + * function(this:jspb.BinaryReader,V, + * function(V,!jspb.BinaryReader))} valueReaderFn + * The method on BinaryReader that reads type V from the stream. May be + * readMessage, in which case the second callback arg form is used. + * + * @param {?function(V,!jspb.BinaryReader)=} opt_valueReaderCallback + * The BinaryReader parsing callback for type V, if V is a message type + * + * @param {K=} opt_defaultKey + * The default value for the type of map keys. Accepting map + * entries with unset keys is required for maps to be backwards compatible + * with the repeated message representation described here: goo.gl/zuoLAC + * + */ +jspb.Map.deserializeBinary = function(map, reader, keyReaderFn, valueReaderFn, + opt_valueReaderCallback, opt_defaultKey) { + var key = opt_defaultKey; + var value = undefined; + + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + + if (field == 1) { + // Key. + key = keyReaderFn.call(reader); + } else if (field == 2) { + // Value. + if (map.valueCtor_) { + goog.asserts.assert(opt_valueReaderCallback); + value = new map.valueCtor_(); + valueReaderFn.call(reader, value, opt_valueReaderCallback); + } else { + value = + (/** @type {function(this:jspb.BinaryReader):?} */ (valueReaderFn)) + .call(reader); + } + } + } + + goog.asserts.assert(key != undefined); + goog.asserts.assert(value != undefined); + map.set(key, value); +}; + + +/** + * Helper: compute the list of all stringified keys in the underlying Object + * map. + * @return {!Array<string>} + * @private + */ +jspb.Map.prototype.stringKeys_ = function() { + var m = this.map_; + var ret = []; + for (var p in m) { + if (Object.prototype.hasOwnProperty.call(m, p)) { + ret.push(p); + } + } + return ret; +}; + + + +/** + * @param {K} key The entry's key. + * @param {V=} opt_value The entry's value wrapper. + * @constructor + * @struct + * @template K, V + * @private + */ +jspb.Map.Entry_ = function(key, opt_value) { + /** @const {K} */ + this.key = key; + + // The JSPB-serializable value. For primitive types this will be of type V. + // For message types it will be an array. + /** @type {V} */ + this.value = opt_value; + + // Only used for submessage values. + /** @type {V} */ + this.valueWrapper = undefined; +}; diff --git a/third_party/protobuf/3.6.0/js/maps_test.js b/third_party/protobuf/3.6.0/js/maps_test.js new file mode 100644 index 0000000000..e496f446bd --- /dev/null +++ b/third_party/protobuf/3.6.0/js/maps_test.js @@ -0,0 +1,388 @@ +// 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'); +goog.require('proto.jspb.test.TestMapFieldsOptionalKeys'); +goog.require('proto.jspb.test.MapEntryOptionalKeysStringKey'); +goog.require('proto.jspb.test.MapEntryOptionalKeysInt32Key'); +goog.require('proto.jspb.test.MapEntryOptionalKeysInt64Key'); +goog.require('proto.jspb.test.MapEntryOptionalKeysBoolKey'); + +// 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); + }); + /** + * Tests deserialization of undefined map keys go to default values in binary format. + */ + it('testMapDeserializationForUndefinedKeys', function() { + var testMessageOptionalKeys = new proto.jspb.test.TestMapFieldsOptionalKeys(); + var mapEntryStringKey = new proto.jspb.test.MapEntryOptionalKeysStringKey(); + mapEntryStringKey.setValue("a"); + testMessageOptionalKeys.setMapStringString(mapEntryStringKey); + var mapEntryInt32Key = new proto.jspb.test.MapEntryOptionalKeysInt32Key(); + mapEntryInt32Key.setValue("b"); + testMessageOptionalKeys.setMapInt32String(mapEntryInt32Key); + var mapEntryInt64Key = new proto.jspb.test.MapEntryOptionalKeysInt64Key(); + mapEntryInt64Key.setValue("c"); + testMessageOptionalKeys.setMapInt64String(mapEntryInt64Key); + var mapEntryBoolKey = new proto.jspb.test.MapEntryOptionalKeysBoolKey(); + mapEntryBoolKey.setValue("d"); + testMessageOptionalKeys.setMapBoolString(mapEntryBoolKey); + var deserializedMessage = msgInfo.deserializeBinary( + testMessageOptionalKeys.serializeBinary() + ); + checkMapEquals(deserializedMessage.getMapStringStringMap(), [ + ['', 'a'] + ]); + checkMapEquals(deserializedMessage.getMapInt32StringMap(), [ + [0, 'b'] + ]); + checkMapEquals(deserializedMessage.getMapInt64StringMap(), [ + [0, 'c'] + ]); + checkMapEquals(deserializedMessage.getMapBoolStringMap(), [ + [false, 'd'] + ]); + }); + } + + + /** + * 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 + }); + + /** + * Returns IteratorIterables for entries(), keys() and values(). + */ + it('testIteratorIterables' + suffix, function() { + var msg = new msgInfo.constructor(); + var m = msg.getMapStringStringMap(); + m.set('key1', 'value1'); + m.set('key2', 'value2'); + var entryIterator = m.entries(); + assertElementsEquals(entryIterator.next().value, ['key1', 'value1']); + assertElementsEquals(entryIterator.next().value, ['key2', 'value2']); + assertEquals(entryIterator.next().done, true); + + if (typeof(Symbol) != 'undefined') { + var entryIterable = m.entries()[Symbol.iterator](); + assertElementsEquals(entryIterable.next().value, ['key1', 'value1']); + assertElementsEquals(entryIterable.next().value, ['key2', 'value2']); + assertEquals(entryIterable.next().done, true); + } + + var keyIterator = m.keys(); + assertEquals(keyIterator.next().value, 'key1'); + assertEquals(keyIterator.next().value, 'key2'); + assertEquals(keyIterator.next().done, true); + + if (typeof(Symbol) != 'undefined') { + var keyIterable = m.keys()[Symbol.iterator](); + assertEquals(keyIterable.next().value, 'key1'); + assertEquals(keyIterable.next().value, 'key2'); + assertEquals(keyIterable.next().done, true); + } + var valueIterator = m.values(); + assertEquals(valueIterator.next().value, 'value1'); + assertEquals(valueIterator.next().value, 'value2'); + assertEquals(valueIterator.next().done, true); + + if (typeof(Symbol) != 'undefined') { + var valueIterable = m.values()[Symbol.iterator](); + assertEquals(valueIterable.next().value, 'value1'); + assertEquals(valueIterable.next().value, 'value2'); + assertEquals(valueIterable.next().done, true); + } + }); +} + +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/third_party/protobuf/3.6.0/js/message.js b/third_party/protobuf/3.6.0/js/message.js new file mode 100644 index 0000000000..86d1829592 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/message.js @@ -0,0 +1,1770 @@ +// 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 Definition of jspb.Message. + * + * @author mwr@google.com (Mark Rawling) + */ + +goog.provide('jspb.ExtensionFieldBinaryInfo'); +goog.provide('jspb.ExtensionFieldInfo'); +goog.provide('jspb.Message'); + +goog.require('goog.array'); +goog.require('goog.asserts'); +goog.require('goog.crypt.base64'); +goog.require('jspb.Map'); + +// Not needed in compilation units that have no protos with xids. +goog.forwardDeclare('xid.String'); + + + +/** + * Stores information for a single extension field. + * + * For example, an extension field defined like so: + * + * extend BaseMessage { + * optional MyMessage my_field = 123; + * } + * + * will result in an ExtensionFieldInfo object with these properties: + * + * { + * fieldIndex: 123, + * fieldName: {my_field_renamed: 0}, + * ctor: proto.example.MyMessage, + * toObjectFn: proto.example.MyMessage.toObject, + * isRepeated: 0 + * } + * + * We include `toObjectFn` to allow the JSCompiler to perform dead-code removal + * on unused toObject() methods. + * + * If an extension field is primitive, ctor and toObjectFn will be null. + * isRepeated should be 0 or 1. + * + * binary{Reader,Writer}Fn and (if message type) binaryMessageSerializeFn are + * always provided. binaryReaderFn and binaryWriterFn are references to the + * appropriate methods on BinaryReader/BinaryWriter to read/write the value of + * this extension, and binaryMessageSerializeFn is a reference to the message + * class's .serializeBinary method, if available. + * + * @param {number} fieldNumber + * @param {Object} fieldName This has the extension field name as a property. + * @param {?function(new: jspb.Message, Array=)} ctor + * @param {?function((boolean|undefined),!jspb.Message):!Object} toObjectFn + * @param {number} isRepeated + * @constructor + * @struct + * @template T + */ +jspb.ExtensionFieldInfo = function(fieldNumber, fieldName, ctor, toObjectFn, + isRepeated) { + /** @const */ + this.fieldIndex = fieldNumber; + /** @const */ + this.fieldName = fieldName; + /** @const */ + this.ctor = ctor; + /** @const */ + this.toObjectFn = toObjectFn; + /** @const */ + this.isRepeated = isRepeated; +}; + +/** + * Stores binary-related information for a single extension field. + * @param {!jspb.ExtensionFieldInfo<T>} fieldInfo + * @param {function(this:jspb.BinaryReader,number,?)} binaryReaderFn + * @param {function(this:jspb.BinaryWriter,number,?) + * |function(this:jspb.BinaryWriter,number,?,?,?,?,?)} binaryWriterFn + * @param {function(?,?)=} opt_binaryMessageSerializeFn + * @param {function(?,?)=} opt_binaryMessageDeserializeFn + * @param {boolean=} opt_isPacked + * @constructor + * @struct + * @template T + */ +jspb.ExtensionFieldBinaryInfo = function(fieldInfo, binaryReaderFn, binaryWriterFn, + opt_binaryMessageSerializeFn, opt_binaryMessageDeserializeFn, opt_isPacked) { + /** @const */ + this.fieldInfo = fieldInfo; + /** @const */ + this.binaryReaderFn = binaryReaderFn; + /** @const */ + this.binaryWriterFn = binaryWriterFn; + /** @const */ + this.binaryMessageSerializeFn = opt_binaryMessageSerializeFn; + /** @const */ + this.binaryMessageDeserializeFn = opt_binaryMessageDeserializeFn; + /** @const */ + this.isPacked = opt_isPacked; +}; + +/** + * @return {boolean} Does this field represent a sub Message? + */ +jspb.ExtensionFieldInfo.prototype.isMessageType = function() { + return !!this.ctor; +}; + + +/** + * Base class for all JsPb messages. + * + * Several common methods (toObject, serializeBinary, in particular) are not + * defined on the prototype to encourage code patterns that minimize code bloat + * due to otherwise unused code on all protos contained in the project. + * + * If you want to call these methods on a generic message, either + * pass in your instance of method as a parameter: + * someFunction(instanceOfKnownProto, + * KnownProtoClass.prototype.serializeBinary); + * or use a lambda that knows the type: + * someFunction(()=>instanceOfKnownProto.serializeBinary()); + * or, if you don't care about code size, just suppress the + * WARNING - Property serializeBinary never defined on jspb.Message + * and call it the intuitive way. + * + * @constructor + * @struct + */ +jspb.Message = function() { +}; + + +/** + * @define {boolean} Whether to generate toObject methods for objects. Turn + * this off, if you do not want toObject to be ever used in your project. + * When turning off this flag, consider adding a conformance test that bans + * calling toObject. Enabling this will disable the JSCompiler's ability to + * dead code eliminate fields used in protocol buffers that are never used + * in an application. + */ +goog.define('jspb.Message.GENERATE_TO_OBJECT', true); + + +/** + * @define {boolean} Whether to generate fromObject methods for objects. Turn + * this off, if you do not want fromObject to be ever used in your project. + * When turning off this flag, consider adding a conformance test that bans + * calling fromObject. Enabling this might disable the JSCompiler's ability + * to dead code eliminate fields used in protocol buffers that are never + * used in an application. + * NOTE: By default no protos actually have a fromObject method. You need to + * add the jspb.generate_from_object options to the proto definition to + * activate the feature. + * By default this is enabled for test code only. + */ +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 not use toString in your project and want to trim it + * from the compiled JS. + */ +goog.define('jspb.Message.GENERATE_TO_STRING', true); + + +/** + * @define {boolean} Whether arrays passed to initialize() can be assumed to be + * local (e.g. not from another iframe) and thus safely classified with + * instanceof Array. + */ +goog.define('jspb.Message.ASSUME_LOCAL_ARRAYS', false); + + +// TODO(jakubvrana): Turn this off by default. +/** + * @define {boolean} Disabling the serialization of empty trailing fields + * reduces the size of serialized protos. The price is an extra iteration of + * the proto before serialization. This is enabled by default to be + * backwards compatible. Projects are advised to turn this flag always off. + */ +goog.define('jspb.Message.SERIALIZE_EMPTY_TRAILING_FIELDS', true); + + +/** + * Does this JavaScript environment support Uint8Aray typed arrays? + * @type {boolean} + * @private + */ +jspb.Message.SUPPORTS_UINT8ARRAY_ = (typeof Uint8Array == 'function'); + + +/** + * The internal data array. + * @type {!Array} + * @protected + */ +jspb.Message.prototype.array; + + +/** + * Wrappers are the constructed instances of message-type fields. They are built + * on demand from the raw array data. Includes message fields, repeated message + * fields and extension message fields. Indexed by field number. + * @type {Object} + * @private + */ +jspb.Message.prototype.wrappers_; + + +/** + * The object that contains extension fields, if any. This is an object that + * maps from a proto field number to the field's value. + * @type {Object} + * @private + */ +jspb.Message.prototype.extensionObject_; + + +/** + * Non-extension fields with a field number at or above the pivot are + * stored in the extension object (in addition to all extension fields). + * @type {number} + * @private + */ +jspb.Message.prototype.pivot_; + + +/** + * The JsPb message_id of this proto. + * @type {string|undefined} the message id or undefined if this message + * has no id. + * @private + */ +jspb.Message.prototype.messageId_; + + +/** + * Repeated float or double fields which have been converted to include only + * numbers and not strings holding "NaN", "Infinity" and "-Infinity". + * @private {!Object<number,boolean>|undefined} + */ +jspb.Message.prototype.convertedFloatingPointFields_; + + +/** + * Repeated fields numbers. + * @protected {?Array<number>|undefined} + */ +jspb.Message.prototype.repeatedFields; + + +/** + * The xid of this proto type (The same for all instances of a proto). Provides + * a way to identify a proto by stable obfuscated name. + * @see {xid}. + * Available if {@link jspb.generate_xid} is added as a Message option to + * a protocol buffer. + * @const {!xid.String|undefined} The xid or undefined if message is + * annotated to generate the xid. + */ +jspb.Message.prototype.messageXid; + + + +/** + * Returns the JsPb message_id of this proto. + * @return {string|undefined} the message id or undefined if this message + * has no id. + */ +jspb.Message.prototype.getJsPbMessageId = function() { + return this.messageId_; +}; + + +/** + * An offset applied to lookups into this.array to account for the presence or + * absence of a messageId at position 0. For response messages, this will be 0. + * Otherwise, it will be -1 so that the first array position is not wasted. + * @type {number} + * @private + */ +jspb.Message.prototype.arrayIndexOffset_; + + +/** + * Returns the index into msg.array at which the proto field with tag number + * fieldNumber will be located. + * @param {!jspb.Message} msg Message for which we're calculating an index. + * @param {number} fieldNumber The field number. + * @return {number} The index. + * @private + */ +jspb.Message.getIndex_ = function(msg, fieldNumber) { + return fieldNumber + msg.arrayIndexOffset_; +}; + + +/** + * Returns the tag number based on the index in msg.array. + * @param {!jspb.Message} msg Message for which we're calculating an index. + * @param {number} index The tag number. + * @return {number} The field number. + * @private + */ +jspb.Message.getFieldNumber_ = function(msg, index) { + return index - msg.arrayIndexOffset_; +}; + + +/** + * Initializes a JsPb Message. + * @param {!jspb.Message} msg The JsPb proto to modify. + * @param {Array|undefined} data An initial data array. + * @param {string|number} messageId For response messages, the message id or '' + * if no message id is specified. For non-response messages, 0. + * @param {number} suggestedPivot The field number at which to start putting + * fields into the extension object. This is only used if data does not + * contain an extension object already. -1 if no extension object is + * required for this message type. + * @param {Array<number>} repeatedFields The message's repeated fields. + * @param {Array<!Array<number>>=} opt_oneofFields The fields belonging to + * each of the message's oneof unions. + * @protected + */ +jspb.Message.initialize = function( + msg, data, messageId, suggestedPivot, repeatedFields, opt_oneofFields) { + msg.wrappers_ = null; + if (!data) { + data = messageId ? [messageId] : []; + } + msg.messageId_ = messageId ? String(messageId) : undefined; + // If the messageId is 0, this message is not a response message, so we shift + // array indices down by 1 so as not to waste the first position in the array, + // which would otherwise go unused. + msg.arrayIndexOffset_ = messageId === 0 ? -1 : 0; + msg.array = data; + jspb.Message.initPivotAndExtensionObject_(msg, suggestedPivot); + msg.convertedFloatingPointFields_ = {}; + + if (!jspb.Message.SERIALIZE_EMPTY_TRAILING_FIELDS) { + // TODO(jakubvrana): This is same for all instances, move to prototype. + // TODO(jakubvrana): There are indexOf calls on this in serializtion, + // consider switching to a set. + msg.repeatedFields = repeatedFields; + } + + if (repeatedFields) { + for (var i = 0; i < repeatedFields.length; i++) { + var fieldNumber = repeatedFields[i]; + if (fieldNumber < msg.pivot_) { + var index = jspb.Message.getIndex_(msg, fieldNumber); + msg.array[index] = + msg.array[index] || jspb.Message.EMPTY_LIST_SENTINEL_; + } else { + jspb.Message.maybeInitEmptyExtensionObject_(msg); + msg.extensionObject_[fieldNumber] = msg.extensionObject_[fieldNumber] || + jspb.Message.EMPTY_LIST_SENTINEL_; + } + } + } + + if (opt_oneofFields && opt_oneofFields.length) { + // Compute the oneof case for each union. This ensures only one value is + // set in the union. + for (var i = 0; i < opt_oneofFields.length; i++) { + jspb.Message.computeOneofCase(msg, opt_oneofFields[i]); + } + } +}; + + +/** + * Used to mark empty repeated fields. Serializes to null when serialized + * to JSON. + * When reading a repeated field readers must check the return value against + * this value and return and replace it with a new empty array if it is + * present. + * @private @const {!Object} + */ +jspb.Message.EMPTY_LIST_SENTINEL_ = goog.DEBUG && Object.freeze ? + Object.freeze([]) : + []; + + +/** + * Returns true if the provided argument is an array. + * @param {*} o The object to classify as array or not. + * @return {boolean} True if the provided object is an array. + * @private + */ +jspb.Message.isArray_ = function(o) { + return jspb.Message.ASSUME_LOCAL_ARRAYS ? o instanceof Array : + goog.isArray(o); +}; + + +/** + * 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, + * 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.initPivotAndExtensionObject_ = function(msg, suggestedPivot) { + if (msg.array.length) { + var foundIndex = msg.array.length - 1; + var obj = msg.array[foundIndex]; + // Normal fields are never objects, so we can be sure that if we find an + // object here, then it's the extension object. However, we must ensure that + // the object is not an array, since arrays are valid field values. + // NOTE(lukestebbing): We avoid looking at .length to avoid a JIT bug + // in Safari on iOS 8. See the description of CL/86511464 for details. + if (obj && typeof obj == 'object' && !jspb.Message.isArray_(obj) && + !(jspb.Message.SUPPORTS_UINT8ARRAY_ && obj instanceof Uint8Array)) { + msg.pivot_ = jspb.Message.getFieldNumber_(msg, foundIndex); + msg.extensionObject_ = obj; + return; + } + } + + if (suggestedPivot > -1) { + msg.pivot_ = suggestedPivot; + // 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; + } +}; + + +/** + * Creates an empty extensionObject_ if non exists. + * @param {!jspb.Message} msg The JsPb proto to modify. + * @private + */ +jspb.Message.maybeInitEmptyExtensionObject_ = function(msg) { + var pivotIndex = jspb.Message.getIndex_(msg, msg.pivot_); + if (!msg.array[pivotIndex]) { + msg.extensionObject_ = msg.array[pivotIndex] = {}; + } +}; + + +/** + * Converts a JsPb repeated message field into an object list. + * @param {!Array<T>} field The repeated message field to be + * converted. + * @param {?function(boolean=): Object| + * function((boolean|undefined),T): Object} toObjectFn The toObject + * function for this field. We need to pass this for effective dead code + * removal. + * @param {boolean=} opt_includeInstance Whether to include the JSPB instance + * for transitional soy proto support: http://goto/soy-param-migration + * @return {!Array<Object>} An array of converted message objects. + * @template T + */ +jspb.Message.toObjectList = function(field, toObjectFn, opt_includeInstance) { + // Not using goog.array.map in the generated code to keep it small. + // And not using it here to avoid a function call. + var result = []; + for (var i = 0; i < field.length; i++) { + result[i] = toObjectFn.call(field[i], opt_includeInstance, field[i]); + } + return result; +}; + + +/** + * Adds a proto's extension data to a Soy rendering object. + * @param {!jspb.Message} proto The proto whose extensions to convert. + * @param {!Object} obj The Soy object to add converted extension data to. + * @param {!Object} extensions The proto class' registered extensions. + * @param {function(this:?, jspb.ExtensionFieldInfo) : *} getExtensionFn + * The proto class' getExtension function. Passed for effective dead code + * removal. + * @param {boolean=} opt_includeInstance Whether to include the JSPB instance + * for transitional soy proto support: http://goto/soy-param-migration + */ +jspb.Message.toObjectExtension = function(proto, obj, extensions, + getExtensionFn, opt_includeInstance) { + for (var fieldNumber in extensions) { + var fieldInfo = extensions[fieldNumber]; + var value = getExtensionFn.call(proto, fieldInfo); + if (value != null) { + for (var name in fieldInfo.fieldName) { + if (fieldInfo.fieldName.hasOwnProperty(name)) { + break; // the compiled field name + } + } + if (!fieldInfo.toObjectFn) { + obj[name] = value; + } else { + if (fieldInfo.isRepeated) { + obj[name] = jspb.Message.toObjectList( + /** @type {!Array<!jspb.Message>} */ (value), + fieldInfo.toObjectFn, opt_includeInstance); + } else { + obj[name] = fieldInfo.toObjectFn( + opt_includeInstance, /** @type {!jspb.Message} */ (value)); + } + } + } + } +}; + + +/** + * Writes a proto's extension data to a binary-format output stream. + * @param {!jspb.Message} proto The proto whose extensions to convert. + * @param {*} writer The binary-format writer to write to. + * @param {!Object} extensions The proto class' registered extensions. + * @param {function(this:jspb.Message,!jspb.ExtensionFieldInfo) : *} getExtensionFn The proto + * class' getExtension function. Passed for effective dead code removal. + */ +jspb.Message.serializeBinaryExtensions = function(proto, writer, extensions, + getExtensionFn) { + for (var fieldNumber in extensions) { + var binaryFieldInfo = extensions[fieldNumber]; + var fieldInfo = binaryFieldInfo.fieldInfo; + + // The old codegen doesn't add the extra fields to ExtensionFieldInfo, so we + // need to gracefully error-out here rather than produce a null dereference + // below. + if (!binaryFieldInfo.binaryWriterFn) { + throw new Error('Message extension present that was generated ' + + 'without binary serialization support'); + } + var value = getExtensionFn.call(proto, fieldInfo); + 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 + // we can't know when we codegen the extending message that the extended + // message may require binary support, so we can *only* catch this error + // here, at runtime (and this decoupled codegen is the whole point of + // extensions!). + if (binaryFieldInfo.binaryMessageSerializeFn) { + binaryFieldInfo.binaryWriterFn.call(writer, fieldInfo.fieldIndex, + value, binaryFieldInfo.binaryMessageSerializeFn); + } else { + throw new Error('Message extension present holding submessage ' + + 'without binary support enabled, and message is ' + + 'being serialized to binary format'); + } + } else { + binaryFieldInfo.binaryWriterFn.call( + writer, fieldInfo.fieldIndex, value); + } + } + } +}; + + +/** + * Reads an extension field from the given reader and, if a valid extension, + * sets the extension value. + * @param {!jspb.Message} msg A jspb proto. + * @param {{ + * skipField:function(this:jspb.BinaryReader), + * getFieldNumber:function(this:jspb.BinaryReader):number + * }} reader + * @param {!Object} extensions The extensions object. + * @param {function(this:jspb.Message,!jspb.ExtensionFieldInfo)} getExtensionFn + * @param {function(this:jspb.Message,!jspb.ExtensionFieldInfo, ?)} setExtensionFn + */ +jspb.Message.readBinaryExtension = function(msg, reader, extensions, + getExtensionFn, setExtensionFn) { + var binaryFieldInfo = extensions[reader.getFieldNumber()]; + if (!binaryFieldInfo) { + reader.skipField(); + return; + } + var fieldInfo = binaryFieldInfo.fieldInfo; + if (!binaryFieldInfo.binaryReaderFn) { + throw new Error('Deserializing extension whose generated code does not ' + + 'support binary format'); + } + + var value; + if (fieldInfo.isMessageType()) { + value = new fieldInfo.ctor(); + binaryFieldInfo.binaryReaderFn.call( + reader, value, binaryFieldInfo.binaryMessageDeserializeFn); + } else { + // All other types. + value = binaryFieldInfo.binaryReaderFn.call(reader); + } + + if (fieldInfo.isRepeated && !binaryFieldInfo.isPacked) { + var currentList = getExtensionFn.call(msg, fieldInfo); + if (!currentList) { + setExtensionFn.call(msg, fieldInfo, [value]); + } else { + currentList.push(value); + } + } else { + setExtensionFn.call(msg, fieldInfo, value); + } +}; + + +/** + * Gets the value of a non-extension field. + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @return {string|number|boolean|Uint8Array|Array|null|undefined} + * The field's value. + * @protected + */ +jspb.Message.getField = 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; + } else { + if (!msg.extensionObject_) { + return undefined; + } + var val = msg.extensionObject_[fieldNumber]; + if (val === jspb.Message.EMPTY_LIST_SENTINEL_) { + return msg.extensionObject_[fieldNumber] = []; + } + return val; + } +}; + + +/** + * 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. + * @return {?number|undefined} The field's value. + * @protected + */ +jspb.Message.getOptionalFloatingPointField = function(msg, fieldNumber) { + var value = jspb.Message.getField(msg, fieldNumber); + // Converts "NaN", "Infinity" and "-Infinity" to their corresponding numbers. + return value == null ? value : +value; +}; + + +/** + * Gets the value of a repeated float or double field. + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @return {!Array<number>} The field's value. + * @protected + */ +jspb.Message.getRepeatedFloatingPointField = function(msg, fieldNumber) { + var values = jspb.Message.getRepeatedField(msg, fieldNumber); + if (!msg.convertedFloatingPointFields_) { + msg.convertedFloatingPointFields_ = {}; + } + if (!msg.convertedFloatingPointFields_[fieldNumber]) { + for (var i = 0; i < values.length; i++) { + // Converts "NaN", "Infinity" and "-Infinity" to their corresponding + // numbers. + values[i] = +values[i]; + } + msg.convertedFloatingPointFields_[fieldNumber] = true; + } + return /** @type {!Array<number>} */ (values); +}; + + +/** + * Coerce a 'bytes' field to a base 64 string. + * @param {string|Uint8Array|null} value + * @return {?string} The field's coerced value. + */ +jspb.Message.bytesAsB64 = function(value) { + if (value == null || goog.isString(value)) { + return value; + } + if (jspb.Message.SUPPORTS_UINT8ARRAY_ && value instanceof Uint8Array) { + return goog.crypt.base64.encodeByteArray(value); + } + goog.asserts.fail('Cannot coerce to b64 string: ' + goog.typeOf(value)); + return null; +}; + + +/** + * Coerce a 'bytes' field to a Uint8Array byte buffer. + * Note that Uint8Array is not supported on IE versions before 10 nor on Opera + * Mini. @see http://caniuse.com/Uint8Array + * @param {string|Uint8Array|null} value + * @return {?Uint8Array} The field's coerced value. + */ +jspb.Message.bytesAsU8 = function(value) { + if (value == null || value instanceof Uint8Array) { + return value; + } + if (goog.isString(value)) { + return goog.crypt.base64.decodeStringToUint8Array(value); + } + goog.asserts.fail('Cannot coerce to Uint8Array: ' + goog.typeOf(value)); + return null; +}; + + +/** + * Coerce a repeated 'bytes' field to an array of base 64 strings. + * Note: the returned array should be treated as immutable. + * @param {!Array<string>|!Array<!Uint8Array>} value + * @return {!Array<string?>} The field's coerced value. + */ +jspb.Message.bytesListAsB64 = function(value) { + jspb.Message.assertConsistentTypes_(value); + if (!value.length || goog.isString(value[0])) { + return /** @type {!Array<string>} */ (value); + } + return goog.array.map(value, jspb.Message.bytesAsB64); +}; + + +/** + * Coerce a repeated 'bytes' field to an array of Uint8Array byte buffers. + * Note: the returned array should be treated as immutable. + * Note that Uint8Array is not supported on IE versions before 10 nor on Opera + * Mini. @see http://caniuse.com/Uint8Array + * @param {!Array<string>|!Array<!Uint8Array>} value + * @return {!Array<Uint8Array?>} The field's coerced value. + */ +jspb.Message.bytesListAsU8 = function(value) { + jspb.Message.assertConsistentTypes_(value); + if (!value.length || value[0] instanceof Uint8Array) { + return /** @type {!Array<!Uint8Array>} */ (value); + } + return goog.array.map(value, jspb.Message.bytesAsU8); +}; + + +/** + * Asserts that all elements of an array are of the same type. + * @param {Array?} array The array to test. + * @private + */ +jspb.Message.assertConsistentTypes_ = function(array) { + if (goog.DEBUG && array && array.length > 1) { + var expected = goog.typeOf(array[0]); + goog.array.forEach(array, function(e) { + if (goog.typeOf(e) != expected) { + goog.asserts.fail('Inconsistent type in JSPB repeated field array. ' + + 'Got ' + goog.typeOf(e) + ' expected ' + expected); + } + }); + } +}; + + +/** + * Gets the value of a non-extension primitive field, with proto3 (non-nullable + * primitives) semantics. Returns `defaultValue` if the field is not otherwise + * set. + * @template T + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {T} defaultValue The default value. + * @return {T} The field's value. + * @protected + */ +jspb.Message.getFieldWithDefault = function(msg, fieldNumber, defaultValue) { + var value = jspb.Message.getField(msg, fieldNumber); + if (value == null) { + return defaultValue; + } else { + return value; + } +}; + + +/** + * Alias for getFieldWithDefault used by older generated code. + * @template T + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {T} defaultValue The default value. + * @return {T} The field's value. + * @protected + */ +jspb.Message.getFieldProto3 = jspb.Message.getFieldWithDefault; + + +/** + * Gets the value of a map field, lazily creating the map container if + * necessary. + * + * This should only be called from generated code, because it requires knowledge + * of serialization/parsing callbacks (which are required by the map at + * construction time, and the map may be constructed here). + * + * @template K, V + * @param {!jspb.Message} msg + * @param {number} fieldNumber + * @param {boolean|undefined} noLazyCreate + * @param {?=} opt_valueCtor + * @return {!jspb.Map<K, V>|undefined} + * @protected + */ +jspb.Message.getMapField = function(msg, fieldNumber, noLazyCreate, + opt_valueCtor) { + if (!msg.wrappers_) { + msg.wrappers_ = {}; + } + // If we already have a map in the map wrappers, return that. + if (fieldNumber in msg.wrappers_) { + return msg.wrappers_[fieldNumber]; + } else if (noLazyCreate) { + return undefined; + } else { + // Wrap the underlying elements array with a Map. + var arr = jspb.Message.getField(msg, fieldNumber); + if (!arr) { + arr = []; + jspb.Message.setField(msg, fieldNumber, arr); + } + return msg.wrappers_[fieldNumber] = + new jspb.Map( + /** @type {!Array<!Array<!Object>>} */ (arr), opt_valueCtor); + } +}; + + +/** + * Sets the value of a non-extension field. + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {string|number|boolean|Uint8Array|Array|undefined} value New value + * @protected + */ +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; + } +}; + + +/** + * Sets the value of a non-extension integer field of a proto3 + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {number} value New value + * @protected + */ +jspb.Message.setProto3IntField = function(msg, fieldNumber, value) { + jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0); +}; + + +/** + * Sets the value of a non-extension integer, handled as string, field of a proto3 + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {number} value New value + * @protected + */ +jspb.Message.setProto3StringIntField = function(msg, fieldNumber, value) { + jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, '0'); +}; + +/** + * Sets the value of a non-extension floating point field of a proto3 + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {number} value New value + * @protected + */ +jspb.Message.setProto3FloatField = function(msg, fieldNumber, value) { + jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0.0); +}; + + +/** + * Sets the value of a non-extension boolean field of a proto3 + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {boolean} value New value + * @protected + */ +jspb.Message.setProto3BooleanField = function(msg, fieldNumber, value) { + jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, false); +}; + + +/** + * Sets the value of a non-extension String field of a proto3 + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {string} value New value + * @protected + */ +jspb.Message.setProto3StringField = function(msg, fieldNumber, value) { + jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, ""); +}; + + +/** + * Sets the value of a non-extension Bytes field of a proto3 + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {!Uint8Array|string} value New value + * @protected + */ +jspb.Message.setProto3BytesField = function(msg, fieldNumber, value) { + jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, ""); +}; + + +/** + * Sets the value of a non-extension enum field of a proto3 + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {number} value New value + * @protected + */ +jspb.Message.setProto3EnumField = function(msg, fieldNumber, value) { + jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0); +}; + + + +/** + * Sets the value of a non-extension primitive field, with proto3 (non-nullable + * primitives) semantics of ignoring values that are equal to the type's + * default. + * @template T + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {!Uint8Array|string|number|boolean|undefined} value New value + * @param {!Uint8Array|string|number|boolean} defaultValue The default value. + * @private + */ +jspb.Message.setFieldIgnoringDefault_ = function( + msg, fieldNumber, value, defaultValue) { + if (value != defaultValue) { + jspb.Message.setField(msg, fieldNumber, value); + } else { + msg.array[jspb.Message.getIndex_(msg, fieldNumber)] = null; + } +}; + + +/** + * Adds a value to a repeated, primitive field. + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {string|number|boolean|!Uint8Array} value New value + * @param {number=} opt_index Index where to put new value. + * @protected + */ +jspb.Message.addToRepeatedField = function(msg, fieldNumber, value, opt_index) { + var arr = jspb.Message.getRepeatedField(msg, fieldNumber); + if (opt_index != undefined) { + arr.splice(opt_index, 0, value); + } else { + arr.push(value); + } +}; + + +/** + * Sets the value of a field in a oneof union and clears all other fields in + * the union. + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {!Array<number>} oneof The fields belonging to the union. + * @param {string|number|boolean|Uint8Array|Array|undefined} value New value + * @protected + */ +jspb.Message.setOneofField = function(msg, fieldNumber, oneof, value) { + var currentCase = jspb.Message.computeOneofCase(msg, oneof); + if (currentCase && currentCase !== fieldNumber && value !== undefined) { + if (msg.wrappers_ && currentCase in msg.wrappers_) { + msg.wrappers_[currentCase] = undefined; + } + jspb.Message.setField(msg, currentCase, undefined); + } + jspb.Message.setField(msg, fieldNumber, value); +}; + + +/** + * Computes the selection in a oneof group for the given message, ensuring + * only one field is set in the process. + * + * According to the protobuf language guide ( + * https://developers.google.com/protocol-buffers/docs/proto#oneof), "if the + * parser encounters multiple members of the same oneof on the wire, only the + * last member seen is used in the parsed message." Since JSPB serializes + * messages to a JSON array, the "last member seen" will always be the field + * with the greatest field number (directly corresponding to the greatest + * array index). + * + * @param {!jspb.Message} msg A jspb proto. + * @param {!Array<number>} oneof The field numbers belonging to the union. + * @return {number} The field number currently set in the union, or 0 if none. + * @protected + */ +jspb.Message.computeOneofCase = function(msg, oneof) { + var oneofField; + var oneofValue; + + for (var i = 0; i < oneof.length; i++) { + var fieldNumber = oneof[i]; + var value = jspb.Message.getField(msg, fieldNumber); + if (value != null) { + oneofField = fieldNumber; + oneofValue = value; + jspb.Message.setField(msg, fieldNumber, undefined); + } + } + + if (oneofField) { + // NB: We know the value is unique, so we can call jspb.Message.setField + // directly instead of jpsb.Message.setOneofField. Also, setOneofField + // calls this function. + jspb.Message.setField(msg, oneofField, oneofValue); + return oneofField; + } + + return 0; +}; + + +/** + * Gets and wraps a proto field on access. + * @param {!jspb.Message} msg A jspb proto. + * @param {function(new:jspb.Message, Array)} ctor Constructor for the field. + * @param {number} fieldNumber The field number. + * @param {number=} opt_required True (1) if this is a required field. + * @return {jspb.Message} The field as a jspb proto. + * @protected + */ +jspb.Message.getWrapperField = function(msg, ctor, fieldNumber, opt_required) { + // TODO(mwr): Consider copying data and/or arrays. + if (!msg.wrappers_) { + msg.wrappers_ = {}; + } + if (!msg.wrappers_[fieldNumber]) { + var data = /** @type {Array} */ (jspb.Message.getField(msg, fieldNumber)); + if (opt_required || data) { + // TODO(mwr): Remove existence test for always valid default protos. + msg.wrappers_[fieldNumber] = new ctor(data); + } + } + return /** @type {jspb.Message} */ (msg.wrappers_[fieldNumber]); +}; + + +/** + * Gets and wraps a repeated proto field on access. + * @param {!jspb.Message} msg A jspb proto. + * @param {function(new:jspb.Message, Array)} ctor Constructor for the field. + * @param {number} fieldNumber The field number. + * @return {Array<!jspb.Message>} The repeated field as an array of protos. + * @protected + */ +jspb.Message.getRepeatedWrapperField = function(msg, ctor, fieldNumber) { + jspb.Message.wrapRepeatedField_(msg, ctor, fieldNumber); + var val = msg.wrappers_[fieldNumber]; + if (val == jspb.Message.EMPTY_LIST_SENTINEL_) { + val = msg.wrappers_[fieldNumber] = []; + } + return /** @type {!Array<!jspb.Message>} */ (val); +}; + + +/** + * Wraps underlying array into proto message representation if it wasn't done + * before. + * @param {!jspb.Message} msg A jspb proto. + * @param {function(new:jspb.Message, ?Array)} ctor Constructor for the field. + * @param {number} fieldNumber The field number. + * @private + */ +jspb.Message.wrapRepeatedField_ = function(msg, ctor, fieldNumber) { + if (!msg.wrappers_) { + msg.wrappers_ = {}; + } + if (!msg.wrappers_[fieldNumber]) { + var data = jspb.Message.getRepeatedField(msg, fieldNumber); + for (var wrappers = [], i = 0; i < data.length; i++) { + wrappers[i] = new ctor(data[i]); + } + msg.wrappers_[fieldNumber] = wrappers; + } +}; + + +/** + * Sets a proto field and syncs it to the backing array. + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {?jspb.Message|?jspb.Map|undefined} value A new value for this proto + * field. + * @protected + */ +jspb.Message.setWrapperField = function(msg, fieldNumber, value) { + if (!msg.wrappers_) { + msg.wrappers_ = {}; + } + var data = value ? value.toArray() : value; + msg.wrappers_[fieldNumber] = value; + jspb.Message.setField(msg, fieldNumber, data); +}; + + +/** + * Sets a proto field in a oneof union and syncs it to the backing array. + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {!Array<number>} oneof The fields belonging to the union. + * @param {jspb.Message|undefined} value A new value for this proto field. + * @protected + */ +jspb.Message.setOneofWrapperField = function(msg, fieldNumber, oneof, value) { + if (!msg.wrappers_) { + msg.wrappers_ = {}; + } + var data = value ? value.toArray() : value; + msg.wrappers_[fieldNumber] = value; + jspb.Message.setOneofField(msg, fieldNumber, oneof, data); +}; + + +/** + * Sets a repeated proto field and syncs it to the backing array. + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {Array<!jspb.Message>|undefined} value An array of protos. + * @protected + */ +jspb.Message.setRepeatedWrapperField = function(msg, fieldNumber, value) { + if (!msg.wrappers_) { + msg.wrappers_ = {}; + } + value = value || []; + for (var data = [], i = 0; i < value.length; i++) { + data[i] = value[i].toArray(); + } + msg.wrappers_[fieldNumber] = value; + jspb.Message.setField(msg, fieldNumber, data); +}; + + +/** + * Add a message to a repeated proto field. + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {T_CHILD|undefined} value Proto that will be added to the + * repeated field. + * @param {function(new:T_CHILD, ?Array=)} ctor The constructor of the + * message type. + * @param {number|undefined} index Index at which to insert the value. + * @return {T_CHILD_NOT_UNDEFINED} proto that was inserted to the repeated field + * @template MessageType + * Use go/closure-ttl to declare a non-undefined version of T_CHILD. Replace the + * undefined in blah|undefined with none. This is necessary because the compiler + * will infer T_CHILD to be |undefined. + * @template T_CHILD + * @template T_CHILD_NOT_UNDEFINED := + * cond(isUnknown(T_CHILD), unknown(), + * mapunion(T_CHILD, (X) => + * cond(eq(X, 'undefined'), none(), X))) + * =: + * @protected + */ +jspb.Message.addToRepeatedWrapperField = function( + msg, fieldNumber, value, ctor, index) { + jspb.Message.wrapRepeatedField_(msg, ctor, fieldNumber); + var wrapperArray = msg.wrappers_[fieldNumber]; + if (!wrapperArray) { + wrapperArray = msg.wrappers_[fieldNumber] = []; + } + var insertedValue = value ? value : new ctor(); + var array = jspb.Message.getRepeatedField(msg, fieldNumber); + if (index != undefined) { + wrapperArray.splice(index, 0, insertedValue); + array.splice(index, 0, insertedValue.toArray()); + } else { + wrapperArray.push(insertedValue); + array.push(insertedValue.toArray()); + } + return insertedValue; +}; + + +/** + * Converts a JsPb repeated message field into a map. The map will contain + * protos unless an optional toObject function is given, in which case it will + * contain objects suitable for Soy rendering. + * @param {!Array<T>} field The repeated message field to be + * converted. + * @param {function() : string?} mapKeyGetterFn The function to get the key of + * the map. + * @param {?function(boolean=): Object| + * function((boolean|undefined),T): Object} opt_toObjectFn The + * toObject function for this field. We need to pass this for effective + * dead code removal. + * @param {boolean=} opt_includeInstance Whether to include the JSPB instance + * for transitional soy proto support: http://goto/soy-param-migration + * @return {!Object<string, Object>} A map of proto or Soy objects. + * @template T + */ +jspb.Message.toMap = function( + field, mapKeyGetterFn, opt_toObjectFn, opt_includeInstance) { + var result = {}; + for (var i = 0; i < field.length; i++) { + result[mapKeyGetterFn.call(field[i])] = opt_toObjectFn ? + opt_toObjectFn.call(field[i], opt_includeInstance, + /** @type {!jspb.Message} */ (field[i])) : field[i]; + } + return result; +}; + + +/** + * Syncs all map fields' contents back to their underlying arrays. + * @private + */ +jspb.Message.prototype.syncMapFields_ = function() { + // This iterates over submessage, map, and repeated fields, which is intended. + // Submessages can contain maps which also need to be synced. + // + // There is a lot of opportunity for optimization here. For example we could + // statically determine that some messages have no submessages with maps and + // optimize this method away for those just by generating one extra static + // boolean per message type. + if (this.wrappers_) { + for (var fieldNumber in this.wrappers_) { + var val = this.wrappers_[fieldNumber]; + if (goog.isArray(val)) { + for (var i = 0; i < val.length; i++) { + if (val[i]) { + val[i].toArray(); + } + } + } else { + // Works for submessages and maps. + if (val) { + val.toArray(); + } + } + } + } +}; + + +/** + * Returns the internal array of this proto. + * <p>Note: If you use this array to construct a second proto, the content + * would then be partially shared between the two protos. + * @return {!Array} The proto represented as an array. + */ +jspb.Message.prototype.toArray = function() { + this.syncMapFields_(); + return this.array; +}; + + + +if (jspb.Message.GENERATE_TO_STRING) { + +/** + * Creates a string representation of the internal data array of this proto. + * <p>NOTE: This string is *not* suitable for use in server requests. + * @return {string} A string representation of this proto. + * @override + */ +jspb.Message.prototype.toString = function() { + this.syncMapFields_(); + return this.array.toString(); +}; + +} + +/** + * Gets the value of the extension field from the extended object. + * @param {jspb.ExtensionFieldInfo<T>} fieldInfo Specifies the field to get. + * @return {T} The value of the field. + * @template T + */ +jspb.Message.prototype.getExtension = function(fieldInfo) { + if (!this.extensionObject_) { + return undefined; + } + if (!this.wrappers_) { + this.wrappers_ = {}; + } + var fieldNumber = fieldInfo.fieldIndex; + if (fieldInfo.isRepeated) { + if (fieldInfo.isMessageType()) { + if (!this.wrappers_[fieldNumber]) { + this.wrappers_[fieldNumber] = + goog.array.map(this.extensionObject_[fieldNumber] || [], + function(arr) { + return new fieldInfo.ctor(arr); + }); + } + return this.wrappers_[fieldNumber]; + } else { + return this.extensionObject_[fieldNumber]; + } + } else { + if (fieldInfo.isMessageType()) { + if (!this.wrappers_[fieldNumber] && this.extensionObject_[fieldNumber]) { + this.wrappers_[fieldNumber] = new fieldInfo.ctor( + /** @type {Array|undefined} */ ( + this.extensionObject_[fieldNumber])); + } + return this.wrappers_[fieldNumber]; + } else { + return this.extensionObject_[fieldNumber]; + } + } +}; + + +/** + * Sets the value of the extension field in the extended object. + * @param {jspb.ExtensionFieldInfo} fieldInfo Specifies the field to set. + * @param {jspb.Message|string|Uint8Array|number|boolean|Array?} value The value + * to set. + * @return {THIS} For chaining + * @this {THIS} + * @template THIS + */ +jspb.Message.prototype.setExtension = function(fieldInfo, value) { + // Cast self, since the inferred THIS is unknown inside the function body. + // https://github.com/google/closure-compiler/issues/1411#issuecomment-232442220 + var self = /** @type {!jspb.Message} */ (this); + if (!self.wrappers_) { + self.wrappers_ = {}; + } + jspb.Message.maybeInitEmptyExtensionObject_(self); + var fieldNumber = fieldInfo.fieldIndex; + if (fieldInfo.isRepeated) { + value = value || []; + if (fieldInfo.isMessageType()) { + self.wrappers_[fieldNumber] = value; + self.extensionObject_[fieldNumber] = goog.array.map( + /** @type {!Array<!jspb.Message>} */ (value), function(msg) { + return msg.toArray(); + }); + } else { + self.extensionObject_[fieldNumber] = value; + } + } else { + if (fieldInfo.isMessageType()) { + self.wrappers_[fieldNumber] = value; + self.extensionObject_[fieldNumber] = + value ? /** @type {!jspb.Message} */ (value).toArray() : value; + } else { + self.extensionObject_[fieldNumber] = value; + } + } + return self; +}; + + +/** + * Creates a difference object between two messages. + * + * The result will contain the top-level fields of m2 that differ from those of + * m1 at any level of nesting. No data is cloned, the result object will + * share its top-level elements with m2 (but not with m1). + * + * Note that repeated fields should not have null/undefined elements, but if + * they do, this operation will treat repeated fields of different length as + * the same if the only difference between them is due to trailing + * null/undefined values. + * + * @param {!jspb.Message} m1 The first message object. + * @param {!jspb.Message} m2 The second message object. + * @return {!jspb.Message} The difference returned as a proto message. + * Note that the returned message may be missing required fields. This is + * currently tolerated in Js, but would cause an error if you tried to + * send such a proto to the server. You can access the raw difference + * array with result.toArray(). + * @throws {Error} If the messages are responses with different types. + */ +jspb.Message.difference = function(m1, m2) { + if (!(m1 instanceof m2.constructor)) { + throw new Error('Messages have different types.'); + } + var arr1 = m1.toArray(); + var arr2 = m2.toArray(); + var res = []; + var start = 0; + var length = arr1.length > arr2.length ? arr1.length : arr2.length; + if (m1.getJsPbMessageId()) { + res[0] = m1.getJsPbMessageId(); + start = 1; + } + for (var i = start; i < length; i++) { + if (!jspb.Message.compareFields(arr1[i], arr2[i])) { + res[i] = arr2[i]; + } + } + return new m1.constructor(res); +}; + + +/** + * Tests whether two messages are equal. + * @param {jspb.Message|undefined} m1 The first message object. + * @param {jspb.Message|undefined} m2 The second message object. + * @return {boolean} true if both messages are null/undefined, or if both are + * of the same type and have the same field values. + */ +jspb.Message.equals = function(m1, m2) { + return m1 == m2 || (!!(m1 && m2) && (m1 instanceof m2.constructor) && + jspb.Message.compareFields(m1.toArray(), m2.toArray())); +}; + + +/** + * Compares two message extension fields recursively. + * @param {!Object} extension1 The first field. + * @param {!Object} extension2 The second field. + * @return {boolean} true if the extensions are null/undefined, or otherwise + * equal. + */ +jspb.Message.compareExtensions = function(extension1, extension2) { + extension1 = extension1 || {}; + extension2 = extension2 || {}; + + var keys = {}; + for (var name in extension1) { + keys[name] = 0; + } + for (var name in extension2) { + keys[name] = 0; + } + for (name in keys) { + if (!jspb.Message.compareFields(extension1[name], extension2[name])) { + return false; + } + } + return true; +}; + + +/** + * Compares two message fields recursively. + * @param {*} field1 The first field. + * @param {*} field2 The second field. + * @return {boolean} true if the fields are null/undefined, or otherwise equal. + */ +jspb.Message.compareFields = function(field1, field2) { + // If the fields are trivially equal, they're equal. + if (field1 == field2) return true; + + if (!goog.isObject(field1) || !goog.isObject(field2)) { + // NaN != NaN so we cover this case. + if ((goog.isNumber(field1) && isNaN(field1)) || + (goog.isNumber(field2) && isNaN(field2))) { + // One of the fields might be a string 'NaN'. + return String(field1) == String(field2); + } + // If the fields aren't trivially equal and one of them isn't an object, + // they can't possibly be equal. + return false; + } + + // We have two objects. If they're different types, they're not equal. + field1 = /** @type {!Object} */(field1); + field2 = /** @type {!Object} */(field2); + if (field1.constructor != field2.constructor) return false; + + // If both are Uint8Arrays, compare them element-by-element. + if (jspb.Message.SUPPORTS_UINT8ARRAY_ && field1.constructor === Uint8Array) { + var bytes1 = /** @type {!Uint8Array} */(field1); + var bytes2 = /** @type {!Uint8Array} */(field2); + if (bytes1.length != bytes2.length) return false; + for (var i = 0; i < bytes1.length; i++) { + if (bytes1[i] != bytes2[i]) return false; + } + return true; + } + + // If they're both Arrays, compare them element by element except for the + // optional extension objects at the end, which we compare separately. + if (field1.constructor === Array) { + var typedField1 = /** @type {!Array<?>} */ (field1); + var typedField2 = /** @type {!Array<?>} */ (field2); + var extension1 = undefined; + var extension2 = undefined; + + var length = Math.max(typedField1.length, typedField2.length); + for (var i = 0; i < length; i++) { + var val1 = typedField1[i]; + var val2 = typedField2[i]; + + if (val1 && (val1.constructor == Object)) { + goog.asserts.assert(extension1 === undefined); + goog.asserts.assert(i === typedField1.length - 1); + extension1 = val1; + val1 = undefined; + } + + if (val2 && (val2.constructor == Object)) { + goog.asserts.assert(extension2 === undefined); + goog.asserts.assert(i === typedField2.length - 1); + extension2 = val2; + val2 = undefined; + } + + if (!jspb.Message.compareFields(val1, val2)) { + return false; + } + } + + if (extension1 || extension2) { + extension1 = extension1 || {}; + extension2 = extension2 || {}; + return jspb.Message.compareExtensions(extension1, extension2); + } + + return true; + } + + // If they're both plain Objects (i.e. extensions), compare them as + // extensions. + if (field1.constructor === Object) { + return jspb.Message.compareExtensions(field1, field2); + } + + throw new Error('Invalid type in JSPB array'); +}; + + +/** + * Templated, type-safe cloneMessage definition. + * @return {THIS} + * @this {THIS} + * @template THIS + */ +jspb.Message.prototype.cloneMessage = function() { + return jspb.Message.cloneMessage(/** @type {!jspb.Message} */ (this)); +}; + +/** + * Alias clone to cloneMessage. goog.object.unsafeClone uses clone to + * efficiently copy objects. Without this alias, copying jspb messages comes + * with a large performance penalty. + * @return {THIS} + * @this {THIS} + * @template THIS + */ +jspb.Message.prototype.clone = function() { + return jspb.Message.cloneMessage(/** @type {!jspb.Message} */ (this)); +}; + +/** + * Static clone function. NOTE: A type-safe method called "cloneMessage" + * exists + * on each generated JsPb class. Do not call this function directly. + * @param {!jspb.Message} msg A message to clone. + * @return {!jspb.Message} A deep clone of the given message. + */ +jspb.Message.clone = function(msg) { + // Although we could include the wrappers, we leave them out here. + return jspb.Message.cloneMessage(msg); +}; + + +/** + * @param {!jspb.Message} msg A message to clone. + * @return {!jspb.Message} A deep clone of the given message. + * @protected + */ +jspb.Message.cloneMessage = function(msg) { + // Although we could include the wrappers, we leave them out here. + return new msg.constructor(jspb.Message.clone_(msg.toArray())); +}; + + +/** + * Takes 2 messages of the same type and copies the contents of the first + * message into the second. After this the 2 messages will equals in terms of + * value semantics but share no state. All data in the destination message will + * be overridden. + * + * @param {MESSAGE} fromMessage Message that will be copied into toMessage. + * @param {MESSAGE} toMessage Message which will receive a copy of fromMessage + * as its contents. + * @template MESSAGE + */ +jspb.Message.copyInto = function(fromMessage, toMessage) { + goog.asserts.assertInstanceof(fromMessage, jspb.Message); + goog.asserts.assertInstanceof(toMessage, jspb.Message); + goog.asserts.assert(fromMessage.constructor == toMessage.constructor, + 'Copy source and target message should have the same type.'); + var copyOfFrom = jspb.Message.clone(fromMessage); + + var to = toMessage.toArray(); + var from = copyOfFrom.toArray(); + + // Empty destination in case it has more values at the end of the array. + to.length = 0; + // and then copy everything from the new to the existing message. + for (var i = 0; i < from.length; i++) { + to[i] = from[i]; + } + + // This is either null or empty for a fresh copy. + toMessage.wrappers_ = copyOfFrom.wrappers_; + // Just a reference into the shared array. + toMessage.extensionObject_ = copyOfFrom.extensionObject_; +}; + + +/** + * Helper for cloning an internal JsPb object. + * @param {!Object} obj A JsPb object, eg, a field, to be cloned. + * @return {!Object} A clone of the input object. + * @private + */ +jspb.Message.clone_ = function(obj) { + var o; + if (goog.isArray(obj)) { + // Allocate array of correct size. + var clonedArray = new Array(obj.length); + // Use array iteration where possible because it is faster than for-in. + for (var i = 0; i < obj.length; i++) { + o = obj[i]; + if (o != null) { + // NOTE:redundant null check existing for NTI compatibility. + // see b/70515949 + clonedArray[i] = (typeof o == 'object') ? + jspb.Message.clone_(goog.asserts.assert(o)) : + o; + } + } + return clonedArray; + } + if (jspb.Message.SUPPORTS_UINT8ARRAY_ && obj instanceof Uint8Array) { + return new Uint8Array(obj); + } + var clone = {}; + for (var key in obj) { + o = obj[key]; + if (o != null) { + // NOTE:redundant null check existing for NTI compatibility. + // see b/70515949 + clone[key] = (typeof o == 'object') ? + jspb.Message.clone_(goog.asserts.assert(o)) : + o; + } + } + return clone; +}; + + +/** + * Registers a JsPb message type id with its constructor. + * @param {string} id The id for this type of message. + * @param {Function} constructor The message constructor. + */ +jspb.Message.registerMessageType = function(id, constructor) { + jspb.Message.registry_[id] = constructor; + // This is needed so we can later access messageId directly on the contructor, + // otherwise it is not available due to 'property collapsing' by the compiler. + /** + * @suppress {strictMissingProperties} messageId is not defined on Function + */ + constructor.messageId = id; +}; + + +/** + * The registry of message ids to message constructors. + * @private + */ +jspb.Message.registry_ = {}; + + +/** + * The extensions registered on MessageSet. This is a map of extension + * field number to field info object. This should be considered as a + * private API. + * + * This is similar to [jspb class name].extensions object for + * non-MessageSet. We special case MessageSet so that we do not need + * to goog.require MessageSet from classes that extends MessageSet. + * + * @type {!Object<number, jspb.ExtensionFieldInfo>} + */ +jspb.Message.messageSetExtensions = {}; + +/** + * @type {!Object<number, jspb.ExtensionFieldBinaryInfo>} + */ +jspb.Message.messageSetExtensionsBinary = {}; diff --git a/third_party/protobuf/3.6.0/js/message_test.js b/third_party/protobuf/3.6.0/js/message_test.js new file mode 100644 index 0000000000..1be4109384 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/message_test.js @@ -0,0 +1,1067 @@ +// 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.string'); +goog.require('goog.testing.PropertyReplacer'); +goog.require('goog.testing.asserts'); +goog.require('goog.userAgent'); + +// CommonJS-LoadFromFile: google-protobuf jspb +goog.require('jspb.Message'); + +// CommonJS-LoadFromFile: test8_pb proto.jspb.exttest.nested +goog.require('proto.jspb.exttest.nested.TestNestedExtensionsMessage'); +goog.require('proto.jspb.exttest.nested.TestOuterMessage'); + +// 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() { + var stubs = new goog.testing.PropertyReplacer(); + + beforeEach(function() { + stubs.set(jspb.Message, 'SERIALIZE_EMPTY_TRAILING_FIELDS', false); + }); + + afterEach(function() { + stubs.reset(); + }); + + 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('testEqualsNonFinite', function() { + assertTrue(jspb.Message.compareFields(NaN, NaN)); + assertTrue(jspb.Message.compareFields(NaN, 'NaN')); + assertTrue(jspb.Message.compareFields('NaN', NaN)); + assertTrue(jspb.Message.compareFields(Infinity, Infinity)); + assertTrue(jspb.Message.compareFields(Infinity, 'Infinity')); + assertTrue(jspb.Message.compareFields('-Infinity', -Infinity)); + assertTrue(jspb.Message.compareFields([NaN], ['NaN'])); + assertFalse(jspb.Message.compareFields(undefined, NaN)); + assertFalse(jspb.Message.compareFields(NaN, undefined)); + }); + + 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('testNestedExtensions', function() { + var extendable = new proto.jspb.exttest.nested.TestNestedExtensionsMessage(); + var extension = new proto.jspb.exttest.nested.TestOuterMessage.NestedExtensionMessage(['s1']); + extendable.setExtension(proto.jspb.exttest.nested.TestOuterMessage.innerExtension, extension); + assertObjectEquals(extension, + extendable.getExtension(proto.jspb.exttest.nested.TestOuterMessage.innerExtension)); + }); + + 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([]); + 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'], 102: ''}]); + var obj = data.toObject(); + assertEquals('str1', obj.str1); + assertEquals('ext1', obj.extField.ext1); + assertEquals('', obj.str); + }); + + 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/third_party/protobuf/3.6.0/js/node_loader.js b/third_party/protobuf/3.6.0/js/node_loader.js new file mode 100644 index 0000000000..79211adda4 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/node_loader.js @@ -0,0 +1,49 @@ +// 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 Loader that handles goog.require() for Node.JS. + */ + +var oldLoader = goog.global.CLOSURE_IMPORT_SCRIPT; + +goog.global.CLOSURE_IMPORT_SCRIPT = function(src, opt_sourceText) { + if (opt_sourceText === undefined) { + try { + // Load from the current directory. + require("./" + src); + return true; + } catch (e) { + // Fall back to the Closure loader. + } + } + + return oldLoader(src, opt_sourceText); +}; diff --git a/third_party/protobuf/3.6.0/js/package.json b/third_party/protobuf/3.6.0/js/package.json new file mode 100644 index 0000000000..325f2dcc58 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/package.json @@ -0,0 +1,26 @@ +{ + "name": "google-protobuf", + "version": "3.6.0", + "description": "Protocol Buffers for JavaScript", + "main": "google-protobuf.js", + "files": [ + "google" + ], + "dependencies": {}, + "devDependencies": { + "glob": "~6.0.4", + "google-closure-compiler": "~20160619.0.0", + "google-closure-library": "~20160125.0.0", + "gulp": "~3.9.0", + "jasmine": "~2.4.1" + }, + "scripts": { + "test": "node ./node_modules/gulp/bin/gulp.js test" + }, + "repository": { + "type": "git", + "url": "https://github.com/google/protobuf/tree/master/js" + }, + "author": "Google Protocol Buffers Team", + "license" : "BSD-3-Clause" +} diff --git a/third_party/protobuf/3.6.0/js/proto3_test.js b/third_party/protobuf/3.6.0/js/proto3_test.js new file mode 100644 index 0000000000..4aed88baab --- /dev/null +++ b/third_party/protobuf/3.6.0/js/proto3_test.js @@ -0,0 +1,411 @@ +// 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'); + +// CommonJS-LoadFromFile: google/protobuf/timestamp_pb proto.google.protobuf +goog.require('proto.google.protobuf.Timestamp'); + +// CommonJS-LoadFromFile: google/protobuf/struct_pb proto.google.protobuf +goog.require('proto.google.protobuf.Struct'); + + +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 default values don't affect equality test. + */ + it('testEqualsProto3', function() { + var msg1 = new proto.jspb.test.TestProto3(); + var msg2 = new proto.jspb.test.TestProto3(); + msg2.setOptionalString(''); + + assertTrue(jspb.Message.equals(msg1, msg2)); + }); + + + /** + * Test setting when a field has default semantics. + */ + it('testSetProto3ToValueAndBackToDefault', function() { + var msg = new proto.jspb.test.TestProto3(); + + // Setting should work normally. + msg.setOptionalString('optionalString'); + assertEquals(msg.getOptionalString(), 'optionalString'); + + // Clearing should work too ... + msg.setOptionalString(''); + assertEquals(msg.getOptionalString(), ''); + + // ... and shouldn't affect the equality with a brand new message. + assertTrue(jspb.Message.equals(msg, new proto.jspb.test.TestProto3())); + }); + + /** + * 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() { + // Default instance. + 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.hasOneofForeignMessage()); + assertFalse(msg.hasOneofString()); + assertFalse(msg.hasOneofBytes()); + + // Integer field. + msg.setOneofUint32(42); + assertEquals(msg.getOneofUint32(), 42); + assertEquals(msg.getOneofForeignMessage(), undefined); + assertEquals(msg.getOneofString(), ''); + assertEquals(msg.getOneofBytes(), ''); + + assertTrue(msg.hasOneofUint32()); + assertFalse(msg.hasOneofForeignMessage()); + assertFalse(msg.hasOneofString()); + assertFalse(msg.hasOneofBytes()); + + // Sub-message field. + 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()); + assertTrue(msg.hasOneofForeignMessage()); + assertFalse(msg.hasOneofString()); + assertFalse(msg.hasOneofBytes()); + + // String field. + msg.setOneofString('hello'); + assertEquals(msg.getOneofUint32(), 0); + assertEquals(msg.getOneofForeignMessage(), undefined); + assertEquals(msg.getOneofString(), 'hello'); + assertEquals(msg.getOneofBytes(), ''); + + assertFalse(msg.hasOneofUint32()); + assertFalse(msg.hasOneofForeignMessage()); + assertTrue(msg.hasOneofString()); + assertFalse(msg.hasOneofBytes()); + + // Bytes field. + 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.hasOneofForeignMessage()); + 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)); + + }); + + it('testTimestampWellKnownType', function() { + var msg = new proto.google.protobuf.Timestamp(); + msg.fromDate(new Date(123456789)); + assertEquals(123456, msg.getSeconds()); + assertEquals(789000000, msg.getNanos()); + var date = msg.toDate(); + assertEquals(123456789, date.getTime()); + }); + + it('testStructWellKnownType', function() { + var jsObj = { + abc: "def", + number: 12345.678, + nullKey: null, + boolKey: true, + listKey: [1, null, true, false, "abc"], + structKey: {foo: "bar", somenum: 123}, + complicatedKey: [{xyz: {abc: [3, 4, null, false]}}, "zzz"] + }; + + var struct = proto.google.protobuf.Struct.fromJavaScript(jsObj); + var jsObj2 = struct.toJavaScript(); + + assertEquals("def", jsObj2.abc); + assertEquals(12345.678, jsObj2.number); + assertEquals(null, jsObj2.nullKey); + assertEquals(true, jsObj2.boolKey); + assertEquals("abc", jsObj2.listKey[4]); + assertEquals("bar", jsObj2.structKey.foo); + assertEquals(4, jsObj2.complicatedKey[0].xyz.abc[1]); + }); +}); diff --git a/third_party/protobuf/3.6.0/js/proto3_test.proto b/third_party/protobuf/3.6.0/js/proto3_test.proto new file mode 100644 index 0000000000..0d073ea03e --- /dev/null +++ b/third_party/protobuf/3.6.0/js/proto3_test.proto @@ -0,0 +1,90 @@ +// 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; + MSG_PROTO3_BAH = 3; +} diff --git a/third_party/protobuf/3.6.0/js/test.proto b/third_party/protobuf/3.6.0/js/test.proto new file mode 100644 index 0000000000..7c881c0dfd --- /dev/null +++ b/third_party/protobuf/3.6.0/js/test.proto @@ -0,0 +1,281 @@ +// 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 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; + 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; +} + +message Deeply { + message Nested { + message Message { + optional int32 count = 1; + } + } +} + diff --git a/third_party/protobuf/3.6.0/js/test2.proto b/third_party/protobuf/3.6.0/js/test2.proto new file mode 100644 index 0000000000..b67f93fa9e --- /dev/null +++ b/third_party/protobuf/3.6.0/js/test2.proto @@ -0,0 +1,60 @@ +// 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; + +import "test.proto"; + +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; +} + +message ForeignNestedFieldMessage { + optional Deeply.Nested.Message deeply_nested_message = 1; +} diff --git a/third_party/protobuf/3.6.0/js/test3.proto b/third_party/protobuf/3.6.0/js/test3.proto new file mode 100644 index 0000000000..940a552ed5 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/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/third_party/protobuf/3.6.0/js/test4.proto b/third_party/protobuf/3.6.0/js/test4.proto new file mode 100644 index 0000000000..cf2451e9cb --- /dev/null +++ b/third_party/protobuf/3.6.0/js/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/third_party/protobuf/3.6.0/js/test5.proto b/third_party/protobuf/3.6.0/js/test5.proto new file mode 100644 index 0000000000..34979517e5 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/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/third_party/protobuf/3.6.0/js/test8.proto b/third_party/protobuf/3.6.0/js/test8.proto new file mode 100644 index 0000000000..2ae80dab67 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/test8.proto @@ -0,0 +1,50 @@ +// 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.nested; + +message TestNestedExtensionsMessage { + optional int32 intfield = 1; + extensions 100 to max; +} + +message TestOuterMessage { + message NestedExtensionMessage { + optional string ext1 = 1; + } + extend TestNestedExtensionsMessage { + optional NestedExtensionMessage inner_extension = 100; + } +} diff --git a/third_party/protobuf/3.6.0/js/test_bootstrap.js b/third_party/protobuf/3.6.0/js/test_bootstrap.js new file mode 100644 index 0000000000..9d00a1c430 --- /dev/null +++ b/third_party/protobuf/3.6.0/js/test_bootstrap.js @@ -0,0 +1,41 @@ +// 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 Sets flags for uncompiled JSUnit tests. + */ + +/** + * Set uncompiled flags. + */ +var CLOSURE_DEFINES = { + // Enable the fromObject method on the message class. + 'jspb.Message.GENERATE_FROM_OBJECT': true +}; diff --git a/third_party/protobuf/3.6.0/js/testbinary.proto b/third_party/protobuf/3.6.0/js/testbinary.proto new file mode 100644 index 0000000000..ed5bdfc68f --- /dev/null +++ b/third_party/protobuf/3.6.0/js/testbinary.proto @@ -0,0 +1,244 @@ +// 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; +} + +// These proto are 'mock map' entries to test the above map deserializing with +// undefined keys. Make sure TestMapFieldsOptionalKeys is written to be +// deserialized by TestMapFields +message MapEntryOptionalKeysStringKey { + optional string key = 1; + optional string value = 2; +} + +message MapEntryOptionalKeysInt32Key { + optional int32 key = 1; + optional string value = 2; +} + +message MapEntryOptionalKeysInt64Key { + optional int64 key = 1; + optional string value = 2; +} + +message MapEntryOptionalKeysBoolKey { + optional bool key = 1; + optional string value = 2; +} + +message TestMapFieldsOptionalKeys { + optional MapEntryOptionalKeysStringKey map_string_string = 1; + optional MapEntryOptionalKeysInt32Key map_int32_string= 8; + optional MapEntryOptionalKeysInt64Key map_int64_string = 9; + optional MapEntryOptionalKeysBoolKey map_bool_string = 10; +} + +// End mock-map entries + +enum MapValueEnum { + MAP_VALUE_FOO = 0; + MAP_VALUE_BAR = 1; + MAP_VALUE_BAZ = 2; +} + +message MapValueMessage { + optional int32 foo = 1; +} diff --git a/third_party/protobuf/3.6.0/js/testempty.proto b/third_party/protobuf/3.6.0/js/testempty.proto new file mode 100644 index 0000000000..960bce4e5c --- /dev/null +++ b/third_party/protobuf/3.6.0/js/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; + |