diff options
Diffstat (limited to 'js')
-rw-r--r-- | js/binary/arith.js | 2 | ||||
-rw-r--r-- | js/binary/constants.js | 19 | ||||
-rw-r--r-- | js/binary/decoder.js | 12 | ||||
-rw-r--r-- | js/binary/encoder.js | 4 | ||||
-rw-r--r-- | js/binary/reader.js | 50 | ||||
-rw-r--r-- | js/binary/utils.js | 12 | ||||
-rw-r--r-- | js/binary/utils_test.js | 2 | ||||
-rw-r--r-- | js/binary/writer.js | 112 | ||||
-rw-r--r-- | js/binary/writer_test.js | 12 | ||||
-rw-r--r-- | js/commonjs/export_testdeps.js | 1 | ||||
-rw-r--r-- | js/debug.js | 11 | ||||
-rw-r--r-- | js/debug_test.js | 11 | ||||
-rw-r--r-- | js/map.js | 31 | ||||
-rwxr-xr-x | js/maps_test.js | 40 | ||||
-rw-r--r-- | js/message.js | 145 | ||||
-rw-r--r-- | js/message_test.js | 23 | ||||
-rw-r--r-- | js/package.json | 2 | ||||
-rw-r--r-- | js/testbinary.proto | 32 |
18 files changed, 367 insertions, 154 deletions
diff --git a/js/binary/arith.js b/js/binary/arith.js index 70257de7..62528a26 100644 --- a/js/binary/arith.js +++ b/js/binary/arith.js @@ -221,7 +221,7 @@ jspb.arith.UInt64.prototype.mul = function(a) { * 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], + * @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) { diff --git a/js/binary/constants.js b/js/binary/constants.js index 75a8a52c..21c5889c 100644 --- a/js/binary/constants.js +++ b/js/binary/constants.js @@ -60,14 +60,25 @@ goog.forwardDeclare('jsproto.BinaryExtension'); /** - * Base interface class for all const messages. Does __not__ define any - * methods, as doing so on a widely-used interface defeats dead-code - * elimination. + * 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 @@ -97,6 +108,7 @@ 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; @@ -108,6 +120,7 @@ jspb.RepeatedFieldType; * @typedef {jspb.ScalarFieldType| jspb.RepeatedFieldType| !Uint8Array| + !jspb.ConstBinaryMessage| !jspb.BinaryMessage| !jsproto.BinaryExtension} */ diff --git a/js/binary/decoder.js b/js/binary/decoder.js index 4ec3cada..e33bf1be 100644 --- a/js/binary/decoder.js +++ b/js/binary/decoder.js @@ -58,7 +58,7 @@ goog.require('jspb.utils'); * @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 + * @param {?Array<number|boolean|string>=} opt_elements * @constructor * @struct */ @@ -92,7 +92,7 @@ jspb.BinaryIterator = function(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 + * @param {?Array<number|boolean|string>=} opt_elements * @private */ jspb.BinaryIterator.prototype.init_ = @@ -112,7 +112,7 @@ jspb.BinaryIterator.prototype.init_ = /** * Global pool of BinaryIterator instances. - * @private {!Array.<!jspb.BinaryIterator>} + * @private {!Array<!jspb.BinaryIterator>} */ jspb.BinaryIterator.instanceCache_ = []; @@ -123,7 +123,7 @@ jspb.BinaryIterator.instanceCache_ = []; * @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 + * @param {?Array<number|boolean|string>=} opt_elements * @return {!jspb.BinaryIterator} */ jspb.BinaryIterator.alloc = function(opt_decoder, opt_next, opt_elements) { @@ -274,7 +274,7 @@ jspb.BinaryDecoder = function(opt_bytes, opt_start, opt_length) { /** * Global pool of BinaryDecoder instances. - * @private {!Array.<!jspb.BinaryDecoder>} + * @private {!Array<!jspb.BinaryDecoder>} */ jspb.BinaryDecoder.instanceCache_ = []; @@ -986,7 +986,7 @@ jspb.BinaryDecoder.prototype.readString = function(length) { codeUnits.push(high, low); } - // Avoid exceeding the maximum stack size when calling {@code apply}. + // Avoid exceeding the maximum stack size when calling `apply`. if (codeUnits.length >= 8192) { result += String.fromCharCode.apply(null, codeUnits); codeUnits.length = 0; diff --git a/js/binary/encoder.js b/js/binary/encoder.js index 8e9f5bbc..b2013f63 100644 --- a/js/binary/encoder.js +++ b/js/binary/encoder.js @@ -51,7 +51,7 @@ goog.require('jspb.utils'); * @struct */ jspb.BinaryEncoder = function() { - /** @private {!Array.<number>} */ + /** @private {!Array<number>} */ this.buffer_ = []; }; @@ -65,7 +65,7 @@ jspb.BinaryEncoder.prototype.length = function() { /** - * @return {!Array.<number>} + * @return {!Array<number>} */ jspb.BinaryEncoder.prototype.end = function() { var buffer = this.buffer_; diff --git a/js/binary/reader.js b/js/binary/reader.js index d5d698f7..2dc3eb70 100644 --- a/js/binary/reader.js +++ b/js/binary/reader.js @@ -97,7 +97,7 @@ jspb.BinaryReader = function(opt_bytes, opt_start, opt_length) { /** * User-defined reader callbacks. - * @private {Object.<string, function(!jspb.BinaryReader):*>} + * @private {Object<string, function(!jspb.BinaryReader):*>} */ this.readCallbacks_ = null; }; @@ -105,7 +105,7 @@ jspb.BinaryReader = function(opt_bytes, opt_start, opt_length) { /** * Global pool of BinaryReader instances. - * @private {!Array.<!jspb.BinaryReader>} + * @private {!Array<!jspb.BinaryReader>} */ jspb.BinaryReader.instanceCache_ = []; @@ -992,7 +992,7 @@ jspb.BinaryReader.prototype.readPackedField_ = function(decodeMethod) { /** * Reads a packed int32 field, which consists of a length header and a list of * signed varints. - * @return {!Array.<number>} + * @return {!Array<number>} */ jspb.BinaryReader.prototype.readPackedInt32 = function() { return this.readPackedField_(this.decoder_.readSignedVarint32); @@ -1002,7 +1002,7 @@ jspb.BinaryReader.prototype.readPackedInt32 = function() { /** * 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>} + * @return {!Array<string>} */ jspb.BinaryReader.prototype.readPackedInt32String = function() { return this.readPackedField_(this.decoder_.readSignedVarint32String); @@ -1012,7 +1012,7 @@ jspb.BinaryReader.prototype.readPackedInt32String = function() { /** * Reads a packed int64 field, which consists of a length header and a list of * signed varints. - * @return {!Array.<number>} + * @return {!Array<number>} */ jspb.BinaryReader.prototype.readPackedInt64 = function() { return this.readPackedField_(this.decoder_.readSignedVarint64); @@ -1022,7 +1022,7 @@ jspb.BinaryReader.prototype.readPackedInt64 = function() { /** * 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>} + * @return {!Array<string>} */ jspb.BinaryReader.prototype.readPackedInt64String = function() { return this.readPackedField_(this.decoder_.readSignedVarint64String); @@ -1032,7 +1032,7 @@ jspb.BinaryReader.prototype.readPackedInt64String = function() { /** * Reads a packed uint32 field, which consists of a length header and a list of * unsigned varints. - * @return {!Array.<number>} + * @return {!Array<number>} */ jspb.BinaryReader.prototype.readPackedUint32 = function() { return this.readPackedField_(this.decoder_.readUnsignedVarint32); @@ -1042,7 +1042,7 @@ jspb.BinaryReader.prototype.readPackedUint32 = function() { /** * 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>} + * @return {!Array<string>} */ jspb.BinaryReader.prototype.readPackedUint32String = function() { return this.readPackedField_(this.decoder_.readUnsignedVarint32String); @@ -1052,7 +1052,7 @@ jspb.BinaryReader.prototype.readPackedUint32String = function() { /** * Reads a packed uint64 field, which consists of a length header and a list of * unsigned varints. - * @return {!Array.<number>} + * @return {!Array<number>} */ jspb.BinaryReader.prototype.readPackedUint64 = function() { return this.readPackedField_(this.decoder_.readUnsignedVarint64); @@ -1062,7 +1062,7 @@ jspb.BinaryReader.prototype.readPackedUint64 = function() { /** * 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>} + * @return {!Array<string>} */ jspb.BinaryReader.prototype.readPackedUint64String = function() { return this.readPackedField_(this.decoder_.readUnsignedVarint64String); @@ -1072,7 +1072,7 @@ jspb.BinaryReader.prototype.readPackedUint64String = function() { /** * Reads a packed sint32 field, which consists of a length header and a list of * zigzag varints. - * @return {!Array.<number>} + * @return {!Array<number>} */ jspb.BinaryReader.prototype.readPackedSint32 = function() { return this.readPackedField_(this.decoder_.readZigzagVarint32); @@ -1082,7 +1082,7 @@ jspb.BinaryReader.prototype.readPackedSint32 = function() { /** * Reads a packed sint64 field, which consists of a length header and a list of * zigzag varints. - * @return {!Array.<number>} + * @return {!Array<number>} */ jspb.BinaryReader.prototype.readPackedSint64 = function() { return this.readPackedField_(this.decoder_.readZigzagVarint64); @@ -1092,7 +1092,7 @@ jspb.BinaryReader.prototype.readPackedSint64 = function() { /** * 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>} + * @return {!Array<string>} */ jspb.BinaryReader.prototype.readPackedSint64String = function() { return this.readPackedField_(this.decoder_.readZigzagVarint64String); @@ -1102,7 +1102,7 @@ jspb.BinaryReader.prototype.readPackedSint64String = function() { /** * Reads a packed fixed32 field, which consists of a length header and a list * of unsigned 32-bit ints. - * @return {!Array.<number>} + * @return {!Array<number>} */ jspb.BinaryReader.prototype.readPackedFixed32 = function() { return this.readPackedField_(this.decoder_.readUint32); @@ -1112,7 +1112,7 @@ jspb.BinaryReader.prototype.readPackedFixed32 = function() { /** * Reads a packed fixed64 field, which consists of a length header and a list * of unsigned 64-bit ints. - * @return {!Array.<number>} + * @return {!Array<number>} */ jspb.BinaryReader.prototype.readPackedFixed64 = function() { return this.readPackedField_(this.decoder_.readUint64); @@ -1122,7 +1122,7 @@ jspb.BinaryReader.prototype.readPackedFixed64 = function() { /** * 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>} + * @return {!Array<number>} */ jspb.BinaryReader.prototype.readPackedFixed64String = function() { return this.readPackedField_(this.decoder_.readUint64String); @@ -1132,7 +1132,7 @@ jspb.BinaryReader.prototype.readPackedFixed64String = function() { /** * Reads a packed sfixed32 field, which consists of a length header and a list * of 32-bit ints. - * @return {!Array.<number>} + * @return {!Array<number>} */ jspb.BinaryReader.prototype.readPackedSfixed32 = function() { return this.readPackedField_(this.decoder_.readInt32); @@ -1142,7 +1142,7 @@ jspb.BinaryReader.prototype.readPackedSfixed32 = function() { /** * Reads a packed sfixed64 field, which consists of a length header and a list * of 64-bit ints. - * @return {!Array.<number>} + * @return {!Array<number>} */ jspb.BinaryReader.prototype.readPackedSfixed64 = function() { return this.readPackedField_(this.decoder_.readInt64); @@ -1152,7 +1152,7 @@ jspb.BinaryReader.prototype.readPackedSfixed64 = function() { /** * 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>} + * @return {!Array<string>} */ jspb.BinaryReader.prototype.readPackedSfixed64String = function() { return this.readPackedField_(this.decoder_.readInt64String); @@ -1162,7 +1162,7 @@ jspb.BinaryReader.prototype.readPackedSfixed64String = function() { /** * Reads a packed float field, which consists of a length header and a list of * floats. - * @return {!Array.<number>} + * @return {!Array<number>} */ jspb.BinaryReader.prototype.readPackedFloat = function() { return this.readPackedField_(this.decoder_.readFloat); @@ -1172,7 +1172,7 @@ jspb.BinaryReader.prototype.readPackedFloat = function() { /** * Reads a packed double field, which consists of a length header and a list of * doubles. - * @return {!Array.<number>} + * @return {!Array<number>} */ jspb.BinaryReader.prototype.readPackedDouble = function() { return this.readPackedField_(this.decoder_.readDouble); @@ -1182,7 +1182,7 @@ jspb.BinaryReader.prototype.readPackedDouble = function() { /** * Reads a packed bool field, which consists of a length header and a list of * unsigned varints. - * @return {!Array.<boolean>} + * @return {!Array<boolean>} */ jspb.BinaryReader.prototype.readPackedBool = function() { return this.readPackedField_(this.decoder_.readBool); @@ -1192,7 +1192,7 @@ jspb.BinaryReader.prototype.readPackedBool = function() { /** * Reads a packed enum field, which consists of a length header and a list of * unsigned varints. - * @return {!Array.<number>} + * @return {!Array<number>} */ jspb.BinaryReader.prototype.readPackedEnum = function() { return this.readPackedField_(this.decoder_.readEnum); @@ -1202,7 +1202,7 @@ jspb.BinaryReader.prototype.readPackedEnum = function() { /** * Reads a packed varint hash64 field, which consists of a length header and a * list of varint hash64s. - * @return {!Array.<string>} + * @return {!Array<string>} */ jspb.BinaryReader.prototype.readPackedVarintHash64 = function() { return this.readPackedField_(this.decoder_.readVarintHash64); @@ -1212,7 +1212,7 @@ jspb.BinaryReader.prototype.readPackedVarintHash64 = function() { /** * Reads a packed fixed hash64 field, which consists of a length header and a * list of fixed hash64s. - * @return {!Array.<string>} + * @return {!Array<string>} */ jspb.BinaryReader.prototype.readPackedFixedHash64 = function() { return this.readPackedField_(this.decoder_.readFixedHash64); diff --git a/js/binary/utils.js b/js/binary/utils.js index c706bff4..55a9ccd4 100644 --- a/js/binary/utils.js +++ b/js/binary/utils.js @@ -431,7 +431,7 @@ jspb.utils.joinHash64 = function(bitsLow, bitsHigh) { /** * Individual digits for number->string conversion. - * @const {!Array.<string>} + * @const {!Array<string>} */ jspb.utils.DIGITS = [ '0', '1', '2', '3', '4', '5', '6', '7', @@ -554,10 +554,10 @@ jspb.utils.hash64ToDecimalString = function(hash, signed) { /** * Converts an array of 8-character hash strings into their decimal * representations. - * @param {!Array.<string>} hashes The array of hash strings to convert. + * @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>} + * @return {!Array<string>} */ jspb.utils.hash64ArrayToDecimalStrings = function(hashes, signed) { var result = new Array(hashes.length); @@ -971,8 +971,12 @@ jspb.utils.byteSourceToUint8Array = function(data) { return /** @type {!Uint8Array} */(new Uint8Array(data)); } + if (data.constructor === Buffer) { + return /** @type {!Uint8Array} */(new Uint8Array(data)); + } + if (data.constructor === Array) { - data = /** @type {!Array.<number>} */(data); + data = /** @type {!Array<number>} */(data); return /** @type {!Uint8Array} */(new Uint8Array(data)); } diff --git a/js/binary/utils_test.js b/js/binary/utils_test.js index 6b481dce..13450644 100644 --- a/js/binary/utils_test.js +++ b/js/binary/utils_test.js @@ -657,7 +657,7 @@ describe('binaryUtilsTest', function() { // Converting Uint8Arrays into Uint8Arrays should be a no-op. assertEquals(sourceBytes, convert(sourceBytes)); - // Converting Array.<numbers> into Uint8Arrays should work. + // Converting Array<numbers> into Uint8Arrays should work. check(convert(sourceData)); // Converting ArrayBuffers into Uint8Arrays should work. diff --git a/js/binary/writer.js b/js/binary/writer.js index 037e92b2..287d29c3 100644 --- a/js/binary/writer.js +++ b/js/binary/writer.js @@ -102,7 +102,7 @@ jspb.BinaryWriter = function() { * 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>>} + * @private {!Array<!Array<number>>} */ this.bookmarks_ = []; }; @@ -126,7 +126,7 @@ jspb.BinaryWriter.prototype.appendUint8Array_ = function(arr) { * 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>} + * @return {!Array<number>} * @private */ jspb.BinaryWriter.prototype.beginDelimited_ = function(field) { @@ -143,7 +143,7 @@ jspb.BinaryWriter.prototype.beginDelimited_ = function(field) { * 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 + * @param {!Array<number>} bookmark * @private */ jspb.BinaryWriter.prototype.endDelimited_ = function(bookmark) { @@ -236,10 +236,12 @@ jspb.BinaryWriter.prototype.getResultBuffer = function() { /** * 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() { - return goog.crypt.base64.encodeByteArray(this.getResultBuffer()); +jspb.BinaryWriter.prototype.getResultBase64String = function(opt_webSafe) { + return goog.crypt.base64.encodeByteArray(this.getResultBuffer(), opt_webSafe); }; @@ -855,7 +857,7 @@ jspb.BinaryWriter.prototype.writeVarintHash64 = function(field, 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedInt32 = function(field, value) { if (value == null) return; @@ -869,7 +871,7 @@ jspb.BinaryWriter.prototype.writeRepeatedInt32 = function(field, value) { * 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. + * @param {?Array<string>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedInt32String = function(field, value) { if (value == null) return; @@ -882,7 +884,7 @@ jspb.BinaryWriter.prototype.writeRepeatedInt32String = function(field, value) { /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedInt64 = function(field, value) { if (value == null) return; @@ -896,7 +898,7 @@ jspb.BinaryWriter.prototype.writeRepeatedInt64 = function(field, value) { * 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. + * @param {?Array<string>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedInt64String = function(field, value) { if (value == null) return; @@ -910,7 +912,7 @@ jspb.BinaryWriter.prototype.writeRepeatedInt64String = function(field, value) { * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedUint32 = function(field, value) { if (value == null) return; @@ -924,7 +926,7 @@ jspb.BinaryWriter.prototype.writeRepeatedUint32 = function(field, value) { * 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. + * @param {?Array<string>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedUint32String = function(field, value) { if (value == null) return; @@ -938,7 +940,7 @@ jspb.BinaryWriter.prototype.writeRepeatedUint32String = function(field, value) { * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedUint64 = function(field, value) { if (value == null) return; @@ -952,7 +954,7 @@ jspb.BinaryWriter.prototype.writeRepeatedUint64 = function(field, value) { * 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. + * @param {?Array<string>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedUint64String = function(field, value) { if (value == null) return; @@ -965,7 +967,7 @@ jspb.BinaryWriter.prototype.writeRepeatedUint64String = function(field, value) { /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedSint32 = function(field, value) { if (value == null) return; @@ -978,7 +980,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSint32 = function(field, value) { /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedSint64 = function(field, value) { if (value == null) return; @@ -991,7 +993,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSint64 = function(field, value) { /** * 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. + * @param {?Array<string>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedSint64String = function(field, value) { if (value == null) return; @@ -1005,7 +1007,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSint64String = function(field, value) { * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedFixed32 = function(field, value) { if (value == null) return; @@ -1019,7 +1021,7 @@ jspb.BinaryWriter.prototype.writeRepeatedFixed32 = function(field, value) { * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedFixed64 = function(field, value) { if (value == null) return; @@ -1033,7 +1035,7 @@ jspb.BinaryWriter.prototype.writeRepeatedFixed64 = function(field, value) { * 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. + * @param {?Array<string>} value The array of decimal strings to write. */ jspb.BinaryWriter.prototype.writeRepeatedFixed64String = function( field, value) { @@ -1047,7 +1049,7 @@ jspb.BinaryWriter.prototype.writeRepeatedFixed64String = function( /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedSfixed32 = function(field, value) { if (value == null) return; @@ -1060,7 +1062,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSfixed32 = function(field, value) { /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedSfixed64 = function(field, value) { if (value == null) return; @@ -1074,7 +1076,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSfixed64 = function(field, value) { * 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. + * @param {?Array<string>} value The array of decimal strings to write. */ jspb.BinaryWriter.prototype.writeRepeatedSfixed64String = function(field, value) { if (value == null) return; @@ -1087,7 +1089,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSfixed64String = function(field, value) /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedFloat = function(field, value) { if (value == null) return; @@ -1100,7 +1102,7 @@ jspb.BinaryWriter.prototype.writeRepeatedFloat = function(field, value) { /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedDouble = function(field, value) { if (value == null) return; @@ -1113,7 +1115,7 @@ jspb.BinaryWriter.prototype.writeRepeatedDouble = function(field, value) { /** * 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. + * @param {?Array<boolean>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedBool = function(field, value) { if (value == null) return; @@ -1126,7 +1128,7 @@ jspb.BinaryWriter.prototype.writeRepeatedBool = function(field, value) { /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedEnum = function(field, value) { if (value == null) return; @@ -1139,7 +1141,7 @@ jspb.BinaryWriter.prototype.writeRepeatedEnum = function(field, value) { /** * 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. + * @param {?Array<string>} value The array of strings to write. */ jspb.BinaryWriter.prototype.writeRepeatedString = function(field, value) { if (value == null) return; @@ -1152,7 +1154,7 @@ jspb.BinaryWriter.prototype.writeRepeatedString = function(field, value) { /** * 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 + * @param {?Array<!jspb.ByteSource>} value The arrays of arrays of bytes to * write. */ jspb.BinaryWriter.prototype.writeRepeatedBytes = function(field, value) { @@ -1167,7 +1169,7 @@ jspb.BinaryWriter.prototype.writeRepeatedBytes = function(field, value) { * 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 + * @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. @@ -1187,7 +1189,7 @@ jspb.BinaryWriter.prototype.writeRepeatedMessage = function( * 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 + * @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. @@ -1207,7 +1209,7 @@ jspb.BinaryWriter.prototype.writeRepeatedGroup = function( * 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. + * @param {?Array<string>} value The array of hashes to write. */ jspb.BinaryWriter.prototype.writeRepeatedFixedHash64 = function(field, value) { @@ -1222,7 +1224,7 @@ jspb.BinaryWriter.prototype.writeRepeatedFixedHash64 = * 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. + * @param {?Array<string>} value The array of hashes to write. */ jspb.BinaryWriter.prototype.writeRepeatedVarintHash64 = function(field, value) { @@ -1236,7 +1238,7 @@ jspb.BinaryWriter.prototype.writeRepeatedVarintHash64 = /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedInt32 = function(field, value) { if (value == null || !value.length) return; @@ -1252,7 +1254,7 @@ jspb.BinaryWriter.prototype.writePackedInt32 = function(field, value) { * 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 + * @param {?Array<string>} value */ jspb.BinaryWriter.prototype.writePackedInt32String = function(field, value) { if (value == null || !value.length) return; @@ -1267,7 +1269,7 @@ jspb.BinaryWriter.prototype.writePackedInt32String = function(field, value) { /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedInt64 = function(field, value) { if (value == null || !value.length) return; @@ -1283,7 +1285,7 @@ jspb.BinaryWriter.prototype.writePackedInt64 = function(field, value) { * 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 + * @param {?Array<string>} value */ jspb.BinaryWriter.prototype.writePackedInt64String = function(field, value) { if (value == null || !value.length) return; @@ -1299,7 +1301,7 @@ jspb.BinaryWriter.prototype.writePackedInt64String = function(field, value) { /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedUint32 = function(field, value) { if (value == null || !value.length) return; @@ -1315,7 +1317,7 @@ jspb.BinaryWriter.prototype.writePackedUint32 = function(field, value) { * 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 + * @param {?Array<string>} value */ jspb.BinaryWriter.prototype.writePackedUint32String = function(field, value) { @@ -1331,7 +1333,7 @@ jspb.BinaryWriter.prototype.writePackedUint32String = /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedUint64 = function(field, value) { if (value == null || !value.length) return; @@ -1347,7 +1349,7 @@ jspb.BinaryWriter.prototype.writePackedUint64 = function(field, value) { * 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 + * @param {?Array<string>} value */ jspb.BinaryWriter.prototype.writePackedUint64String = function(field, value) { @@ -1364,7 +1366,7 @@ jspb.BinaryWriter.prototype.writePackedUint64String = /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedSint32 = function(field, value) { if (value == null || !value.length) return; @@ -1379,7 +1381,7 @@ jspb.BinaryWriter.prototype.writePackedSint32 = function(field, value) { /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedSint64 = function(field, value) { if (value == null || !value.length) return; @@ -1395,7 +1397,7 @@ jspb.BinaryWriter.prototype.writePackedSint64 = function(field, value) { * 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. + * @param {?Array<string>} value The array of decimal strings to write. */ jspb.BinaryWriter.prototype.writePackedSint64String = function(field, value) { if (value == null || !value.length) return; @@ -1411,7 +1413,7 @@ jspb.BinaryWriter.prototype.writePackedSint64String = function(field, value) { /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedFixed32 = function(field, value) { if (value == null || !value.length) return; @@ -1426,7 +1428,7 @@ jspb.BinaryWriter.prototype.writePackedFixed32 = function(field, value) { /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedFixed64 = function(field, value) { if (value == null || !value.length) return; @@ -1442,7 +1444,7 @@ jspb.BinaryWriter.prototype.writePackedFixed64 = function(field, value) { * 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. + * @param {?Array<string>} value The array of strings to write. */ jspb.BinaryWriter.prototype.writePackedFixed64String = function(field, value) { if (value == null || !value.length) return; @@ -1458,7 +1460,7 @@ jspb.BinaryWriter.prototype.writePackedFixed64String = function(field, value) { /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedSfixed32 = function(field, value) { if (value == null || !value.length) return; @@ -1473,7 +1475,7 @@ jspb.BinaryWriter.prototype.writePackedSfixed32 = function(field, value) { /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedSfixed64 = function(field, value) { if (value == null || !value.length) return; @@ -1488,7 +1490,7 @@ jspb.BinaryWriter.prototype.writePackedSfixed64 = function(field, value) { /** * 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. + * @param {?Array<string>} value The array of decimal strings to write. */ jspb.BinaryWriter.prototype.writePackedSfixed64String = function(field, value) { if (value == null || !value.length) return; @@ -1503,7 +1505,7 @@ jspb.BinaryWriter.prototype.writePackedSfixed64String = function(field, value) { /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedFloat = function(field, value) { if (value == null || !value.length) return; @@ -1518,7 +1520,7 @@ jspb.BinaryWriter.prototype.writePackedFloat = function(field, value) { /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedDouble = function(field, value) { if (value == null || !value.length) return; @@ -1533,7 +1535,7 @@ jspb.BinaryWriter.prototype.writePackedDouble = function(field, value) { /** * 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. + * @param {?Array<boolean>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedBool = function(field, value) { if (value == null || !value.length) return; @@ -1548,7 +1550,7 @@ jspb.BinaryWriter.prototype.writePackedBool = function(field, value) { /** * 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. + * @param {?Array<number>} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedEnum = function(field, value) { if (value == null || !value.length) return; @@ -1564,7 +1566,7 @@ jspb.BinaryWriter.prototype.writePackedEnum = function(field, 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 {?Array.<string>} value The array of hashes to write. + * @param {?Array<string>} value The array of hashes to write. */ jspb.BinaryWriter.prototype.writePackedFixedHash64 = function(field, value) { if (value == null || !value.length) return; @@ -1580,7 +1582,7 @@ jspb.BinaryWriter.prototype.writePackedFixedHash64 = function(field, 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 {?Array.<string>} value The array of hashes to write. + * @param {?Array<string>} value The array of hashes to write. */ jspb.BinaryWriter.prototype.writePackedVarintHash64 = function(field, value) { if (value == null || !value.length) return; diff --git a/js/binary/writer_test.js b/js/binary/writer_test.js index 118eecfc..8a9a1bb0 100644 --- a/js/binary/writer_test.js +++ b/js/binary/writer_test.js @@ -118,4 +118,16 @@ describe('binaryWriterTest', function() { 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/js/commonjs/export_testdeps.js b/js/commonjs/export_testdeps.js index 6f5cd083..96d3f347 100644 --- a/js/commonjs/export_testdeps.js +++ b/js/commonjs/export_testdeps.js @@ -12,6 +12,7 @@ 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'); diff --git a/js/debug.js b/js/debug.js index 46b24853..ba51bbe0 100644 --- a/js/debug.js +++ b/js/debug.js @@ -42,7 +42,7 @@ goog.require('jspb.Message'); /** * Turns a proto into a human readable object that can i.e. be written to the - * console: {@code console.log(jspb.debug.dump(myProto))}. + * 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 @@ -74,15 +74,22 @@ jspb.debug.dump = function(message) { */ 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_); } - var message = thing; // Copy because we don't want type inference on thing. goog.asserts.assert(message instanceof jspb.Message, 'Only messages expected: ' + thing); var ctor = message.constructor; diff --git a/js/debug_test.js b/js/debug_test.js index 702cc76e..d0d646a5 100644 --- a/js/debug_test.js +++ b/js/debug_test.js @@ -41,6 +41,8 @@ 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() { @@ -74,6 +76,15 @@ describe('debugTest', function() { }, 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) { @@ -48,9 +48,9 @@ goog.forwardDeclare('jspb.BinaryWriter'); * * @template K, V * - * @param {!Array<!Array<!Object>>} arr + * @param {!Array<!Array<?>>} arr * - * @param {?function(new:V)|function(new:V,?)=} opt_valueCtor + * @param {?function(new:V, ?=)=} opt_valueCtor * The constructor for type V, if type V is a message type. * * @constructor @@ -118,7 +118,7 @@ jspb.Map.prototype.toArray = function() { strKeys.sort(); for (var i = 0; i < strKeys.length; i++) { var entry = this.map_[strKeys[i]]; - var valueWrapper = /** @type {!Object} */ (entry.valueWrapper); + var valueWrapper = /** @type {?jspb.Message} */ (entry.valueWrapper); if (valueWrapper) { valueWrapper.toArray(); } @@ -165,7 +165,7 @@ jspb.Map.prototype.toObject = function(includeInstance, valueToObject) { * * @template K, V * @param {!Array<!Array<!Object>>} entries - * @param {!function(new:V)|function(new:V,?)} valueCtor + * @param {!function(new:V,?=)} valueCtor * The constructor for type V. * @param {!function(!Object):V} valueFromObject * The fromObject function for type V. @@ -432,7 +432,8 @@ jspb.Map.prototype.serializeBinary = function( valueWriterFn.call(writer, 2, this.wrapEntry_(entry), opt_valueWriterCallback); } else { - valueWriterFn.call(writer, 2, entry.value); + /** @type {function(this:jspb.BinaryWriter,number,?)} */ (valueWriterFn) + .call(writer, 2, entry.value); } writer.endSubMessage(); } @@ -442,7 +443,8 @@ jspb.Map.prototype.serializeBinary = function( /** * 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. + * 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 @@ -456,12 +458,17 @@ jspb.Map.prototype.serializeBinary = function( * 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. + * 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) { - var key = undefined; + opt_valueReaderCallback, opt_defaultKey) { + var key = opt_defaultKey; var value = undefined; while (reader.nextField()) { @@ -469,16 +476,20 @@ jspb.Map.deserializeBinary = function(map, reader, keyReaderFn, valueReaderFn, 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 = valueReaderFn.call(reader); + value = + (/** @type {function(this:jspb.BinaryReader):?} */ (valueReaderFn)) + .call(reader); } } } diff --git a/js/maps_test.js b/js/maps_test.js index e8dd2f21..e496f446 100755 --- a/js/maps_test.js +++ b/js/maps_test.js @@ -35,6 +35,11 @@ goog.require('goog.userAgent'); 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'); @@ -76,7 +81,7 @@ function toArray(iter) { * Helper: generate test methods for this TestMapFields class. * @param {?} msgInfo * @param {?} submessageCtor - * @param {!string} suffix + * @param {string} suffix */ function makeTests(msgInfo, submessageCtor, suffix) { /** @@ -260,6 +265,39 @@ function makeTests(msgInfo, submessageCtor, suffix) { 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'] + ]); + }); } diff --git a/js/message.js b/js/message.js index 1484229d..86d18295 100644 --- a/js/message.js +++ b/js/message.js @@ -205,15 +205,14 @@ goog.define('jspb.Message.GENERATE_TO_STRING', true); goog.define('jspb.Message.ASSUME_LOCAL_ARRAYS', false); +// TODO(jakubvrana): Turn this off by default. /** - * @define {boolean} Turning on this flag does NOT change the behavior of JSPB - * and only affects private internal state. It may, however, break some - * tests that use naive deeply-equals algorithms, because using a proto - * mutates its internal state. - * Projects are advised to turn this flag always on. + * @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.MINIMIZE_MEMORY_ALLOCATIONS', COMPILED); -// TODO(b/19419436) Turn this on by default. +goog.define('jspb.Message.SERIALIZE_EMPTY_TRAILING_FIELDS', true); /** @@ -278,6 +277,13 @@ 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}. @@ -324,6 +330,18 @@ jspb.Message.getIndex_ = function(msg, fieldNumber) { /** + * 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. @@ -340,7 +358,7 @@ jspb.Message.getIndex_ = function(msg, fieldNumber) { */ jspb.Message.initialize = function( msg, data, messageId, suggestedPivot, repeatedFields, opt_oneofFields) { - msg.wrappers_ = jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS ? null : {}; + msg.wrappers_ = null; if (!data) { data = messageId ? [messageId] : []; } @@ -353,22 +371,24 @@ jspb.Message.initialize = function( 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.MINIMIZE_MEMORY_ALLOCATIONS ? - jspb.Message.EMPTY_LIST_SENTINEL_ : - []); + msg.array[index] = + msg.array[index] || jspb.Message.EMPTY_LIST_SENTINEL_; } else { jspb.Message.maybeInitEmptyExtensionObject_(msg); - msg.extensionObject_[fieldNumber] = - msg.extensionObject_[fieldNumber] || - (jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS ? - jspb.Message.EMPTY_LIST_SENTINEL_ : - []); + msg.extensionObject_[fieldNumber] = msg.extensionObject_[fieldNumber] || + jspb.Message.EMPTY_LIST_SENTINEL_; } } } @@ -376,8 +396,9 @@ jspb.Message.initialize = function( if (opt_oneofFields && opt_oneofFields.length) { // Compute the oneof case for each union. This ensures only one value is // set in the union. - goog.array.forEach( - opt_oneofFields, goog.partial(jspb.Message.computeOneofCase, msg)); + for (var i = 0; i < opt_oneofFields.length; i++) { + jspb.Message.computeOneofCase(msg, opt_oneofFields[i]); + } } }; @@ -428,7 +449,7 @@ jspb.Message.initPivotAndExtensionObject_ = function(msg, suggestedPivot) { // 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_ = foundIndex - msg.arrayIndexOffset_; + msg.pivot_ = jspb.Message.getFieldNumber_(msg, foundIndex); msg.extensionObject_ = obj; return; } @@ -480,8 +501,7 @@ jspb.Message.toObjectList = function(field, toObjectFn, opt_includeInstance) { // 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, - /** @type {!jspb.Message} */ (field[i])); + result[i] = toObjectFn.call(field[i], opt_includeInstance, field[i]); } return result; }; @@ -514,10 +534,11 @@ jspb.Message.toObjectExtension = function(proto, obj, extensions, } else { if (fieldInfo.isRepeated) { obj[name] = jspb.Message.toObjectList( - /** @type {!Array<jspb.Message>} */ (value), + /** @type {!Array<!jspb.Message>} */ (value), fieldInfo.toObjectFn, opt_includeInstance); } else { - obj[name] = fieldInfo.toObjectFn(opt_includeInstance, value); + obj[name] = fieldInfo.toObjectFn( + opt_includeInstance, /** @type {!jspb.Message} */ (value)); } } } @@ -902,6 +923,17 @@ jspb.Message.setProto3IntField = function(msg, fieldNumber, value) { /** + * 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. @@ -1043,14 +1075,15 @@ jspb.Message.computeOneofCase = function(msg, oneof) { var oneofField; var oneofValue; - goog.array.forEach(oneof, function(fieldNumber) { + for (var i = 0; i < oneof.length; i++) { + var fieldNumber = oneof[i]; var value = jspb.Message.getField(msg, fieldNumber); - if (goog.isDefAndNotNull(value)) { + 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 @@ -1241,7 +1274,7 @@ jspb.Message.addToRepeatedWrapperField = function( * 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. + * @return {!Object<string, Object>} A map of proto or Soy objects. * @template T */ jspb.Message.toMap = function( @@ -1318,7 +1351,7 @@ jspb.Message.prototype.toString = function() { /** * Gets the value of the extension field from the extended object. - * @param {jspb.ExtensionFieldInfo.<T>} fieldInfo Specifies the field to get. + * @param {jspb.ExtensionFieldInfo<T>} fieldInfo Specifies the field to get. * @return {T} The value of the field. * @template T */ @@ -1381,7 +1414,7 @@ jspb.Message.prototype.setExtension = function(fieldInfo, value) { if (fieldInfo.isMessageType()) { self.wrappers_[fieldNumber] = value; self.extensionObject_[fieldNumber] = goog.array.map( - /** @type {Array<jspb.Message>} */ (value), function(msg) { + /** @type {!Array<!jspb.Message>} */ (value), function(msg) { return msg.toArray(); }); } else { @@ -1390,7 +1423,8 @@ jspb.Message.prototype.setExtension = function(fieldInfo, value) { } else { if (fieldInfo.isMessageType()) { self.wrappers_[fieldNumber] = value; - self.extensionObject_[fieldNumber] = value ? value.toArray() : value; + self.extensionObject_[fieldNumber] = + value ? /** @type {!jspb.Message} */ (value).toArray() : value; } else { self.extensionObject_[fieldNumber] = value; } @@ -1492,9 +1526,15 @@ jspb.Message.compareFields = function(field1, field2) { // If the fields are trivially equal, they're equal. if (field1 == field2) return true; - // If the fields aren't trivially equal and one of them isn't an object, - // they can't possibly be equal. 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; } @@ -1517,24 +1557,26 @@ jspb.Message.compareFields = function(field1, field2) { // 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(field1.length, field2.length); + var length = Math.max(typedField1.length, typedField2.length); for (var i = 0; i < length; i++) { - var val1 = field1[i]; - var val2 = field2[i]; + var val1 = typedField1[i]; + var val2 = typedField2[i]; if (val1 && (val1.constructor == Object)) { goog.asserts.assert(extension1 === undefined); - goog.asserts.assert(i === field1.length - 1); + 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 === field2.length - 1); + goog.asserts.assert(i === typedField2.length - 1); extension2 = val2; val2 = undefined; } @@ -1657,8 +1699,13 @@ jspb.Message.clone_ = function(obj) { 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++) { - if ((o = obj[i]) != null) { - clonedArray[i] = typeof o == 'object' ? jspb.Message.clone_(o) : o; + 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; @@ -1668,8 +1715,13 @@ jspb.Message.clone_ = function(obj) { } var clone = {}; for (var key in obj) { - if ((o = obj[key]) != null) { - clone[key] = typeof o == 'object' ? jspb.Message.clone_(o) : o; + 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; @@ -1685,6 +1737,9 @@ 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; }; @@ -1705,7 +1760,11 @@ jspb.Message.registry_ = {}; * 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>} + * @type {!Object<number, jspb.ExtensionFieldInfo>} */ jspb.Message.messageSetExtensions = {}; + +/** + * @type {!Object<number, jspb.ExtensionFieldBinaryInfo>} + */ jspb.Message.messageSetExtensionsBinary = {}; diff --git a/js/message_test.js b/js/message_test.js index 7d61dacb..1be41093 100644 --- a/js/message_test.js +++ b/js/message_test.js @@ -34,6 +34,7 @@ goog.setTestOnly(); goog.require('goog.json'); goog.require('goog.string'); +goog.require('goog.testing.PropertyReplacer'); goog.require('goog.testing.asserts'); goog.require('goog.userAgent'); @@ -85,6 +86,16 @@ 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([]); @@ -407,6 +418,18 @@ describe('Message test suite', function() { ['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']]); diff --git a/js/package.json b/js/package.json index 5231c846..325f2dcc 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "google-protobuf", - "version": "3.4.1", + "version": "3.6.0", "description": "Protocol Buffers for JavaScript", "main": "google-protobuf.js", "files": [ diff --git a/js/testbinary.proto b/js/testbinary.proto index 116f17fb..ed5bdfc6 100644 --- a/js/testbinary.proto +++ b/js/testbinary.proto @@ -201,6 +201,38 @@ message TestMapFields { 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; |