aboutsummaryrefslogtreecommitdiffhomepage
path: root/js
diff options
context:
space:
mode:
authorGravatar Adam Cozzette <acozzette@google.com>2017-04-27 14:55:53 -0700
committerGravatar Adam Cozzette <acozzette@google.com>2017-04-27 14:55:53 -0700
commit9053033a5076f82cf18b823c31f352e95e5bfd8d (patch)
tree1d2a2611f56e786d7c3e40b8fd1b2e3d9aff9025 /js
parent067b1eec3bf852abaad0844999461baff8a5fdc8 (diff)
parenta6189acd18b00611c1dc7042299ad75486f08a1a (diff)
Merge remote-tracking branch 'remotes/google/3.3.x' into merge-3.3-to-master
Diffstat (limited to 'js')
-rw-r--r--js/binary/decoder.js17
-rw-r--r--js/binary/decoder_test.js19
-rw-r--r--js/binary/encoder.js4
-rw-r--r--js/binary/reader.js2
-rw-r--r--js/binary/utils.js2
-rw-r--r--js/binary/writer.js4
-rw-r--r--js/binary/writer_test.js2
-rw-r--r--js/map.js10
-rw-r--r--js/message.js31
-rw-r--r--js/message_test.js1
-rw-r--r--js/package.json2
11 files changed, 69 insertions, 25 deletions
diff --git a/js/binary/decoder.js b/js/binary/decoder.js
index 26bf3594..ad9cb01b 100644
--- a/js/binary/decoder.js
+++ b/js/binary/decoder.js
@@ -71,7 +71,7 @@ jspb.BinaryIterator = function(opt_decoder, opt_next, opt_elements) {
*/
this.nextMethod_ = null;
- /** @private {Array.<number>} */
+ /** @private {?Array<number|boolean|string>} */
this.elements_ = null;
/** @private {number} */
@@ -100,7 +100,7 @@ jspb.BinaryIterator.prototype.init_ =
this.decoder_ = opt_decoder;
this.nextMethod_ = opt_next;
}
- this.elements_ = opt_elements ? opt_elements : null;
+ this.elements_ = opt_elements || null;
this.cursor_ = 0;
this.nextValue_ = null;
this.atEnd_ = !this.decoder_ && !this.elements_;
@@ -953,6 +953,7 @@ jspb.BinaryDecoder.prototype.readString = function(length) {
var end = cursor + length;
var codeUnits = [];
+ var result = '';
while (cursor < end) {
var c = bytes[cursor++];
if (c < 128) { // Regular 7-bit ASCII.
@@ -973,7 +974,7 @@ jspb.BinaryDecoder.prototype.readString = function(length) {
var c2 = bytes[cursor++];
var c3 = bytes[cursor++];
var c4 = bytes[cursor++];
- // Characters written on 4 bytes have 21 bits for a codepoint.
+ // 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.
@@ -986,10 +987,14 @@ jspb.BinaryDecoder.prototype.readString = function(length) {
var high = ((codepoint >> 10) & 1023) + 0xD800;
codeUnits.push(high, low);
}
+
+ // Avoid exceeding the maximum stack size when calling {@code apply}.
+ if (codeUnits.length >= 8192) {
+ result += String.fromCharCode.apply(null, codeUnits);
+ codeUnits.length = 0;
+ }
}
- // String.fromCharCode.apply is faster than manually appending characters on
- // Chrome 25+, and generates no additional cons string garbage.
- var result = String.fromCharCode.apply(null, codeUnits);
+ result += String.fromCharCode.apply(null, codeUnits);
this.cursor_ = cursor;
return result;
};
diff --git a/js/binary/decoder_test.js b/js/binary/decoder_test.js
index cb8aff96..d0139e29 100644
--- a/js/binary/decoder_test.js
+++ b/js/binary/decoder_test.js
@@ -211,6 +211,25 @@ describe('binaryDecoderTest', function() {
});
/**
+ * 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() {
diff --git a/js/binary/encoder.js b/js/binary/encoder.js
index aee33e7e..f25935f1 100644
--- a/js/binary/encoder.js
+++ b/js/binary/encoder.js
@@ -355,8 +355,8 @@ jspb.BinaryEncoder.prototype.writeInt64 = function(value) {
*/
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));
+ 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);
};
diff --git a/js/binary/reader.js b/js/binary/reader.js
index 8c5a4e88..d5d698f7 100644
--- a/js/binary/reader.js
+++ b/js/binary/reader.js
@@ -971,7 +971,7 @@ jspb.BinaryReader.prototype.readFixedHash64 = function() {
/**
* Reads a packed scalar field using the supplied raw reader function.
- * @param {function()} decodeMethod
+ * @param {function(this:jspb.BinaryDecoder)} decodeMethod
* @return {!Array}
* @private
*/
diff --git a/js/binary/utils.js b/js/binary/utils.js
index 3ecd08e9..7702020b 100644
--- a/js/binary/utils.js
+++ b/js/binary/utils.js
@@ -430,7 +430,7 @@ jspb.utils.joinHash64 = function(bitsLow, bitsHigh) {
/**
* Individual digits for number->string conversion.
- * @const {!Array.<number>}
+ * @const {!Array.<string>}
*/
jspb.utils.DIGITS = [
'0', '1', '2', '3', '4', '5', '6', '7',
diff --git a/js/binary/writer.js b/js/binary/writer.js
index c3009dbb..672e94bd 100644
--- a/js/binary/writer.js
+++ b/js/binary/writer.js
@@ -596,8 +596,8 @@ jspb.BinaryWriter.prototype.writeSint64 = function(field, value) {
*/
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));
+ goog.asserts.assert((+value >= -jspb.BinaryConstants.TWO_TO_63) &&
+ (+value < jspb.BinaryConstants.TWO_TO_63));
this.writeZigzagVarint64String_(field, value);
};
diff --git a/js/binary/writer_test.js b/js/binary/writer_test.js
index 83fcdf91..118eecfc 100644
--- a/js/binary/writer_test.js
+++ b/js/binary/writer_test.js
@@ -47,7 +47,7 @@ goog.require('jspb.BinaryWriter');
* @param {function()} func This function should throw an error when run.
*/
function assertFails(func) {
- var e = assertThrows(func);
+ assertThrows(func);
}
diff --git a/js/map.js b/js/map.js
index 4f562dbc..d423499f 100644
--- a/js/map.js
+++ b/js/map.js
@@ -136,7 +136,7 @@ jspb.Map.prototype.toArray = function() {
*
* @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
+ * @param {!function((boolean|undefined),V):!Object=} valueToObject
* The static toObject() method, if V is a message type.
* @return {!Array<!Array<!Object>>}
*/
@@ -146,7 +146,7 @@ jspb.Map.prototype.toObject = function(includeInstance, valueToObject) {
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);
+ var valueWrapper = /** @type {V|undefined} */ (entry.valueWrapper);
if (valueWrapper) {
goog.asserts.assert(valueToObject);
entries.push([entry.key, valueToObject(includeInstance, valueWrapper)]);
@@ -412,8 +412,8 @@ jspb.Map.prototype.has = function(key) {
* @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.BinaryReader,V,?)} valueWriterFn
+ * @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
@@ -509,7 +509,7 @@ jspb.Map.prototype.stringKeys_ = function() {
/**
- * @param {!K} key The entry's key.
+ * @param {K} key The entry's key.
* @param {V=} opt_value The entry's value wrapper.
* @constructor
* @struct
diff --git a/js/message.js b/js/message.js
index 220a5bdb..1f6bf16b 100644
--- a/js/message.js
+++ b/js/message.js
@@ -106,8 +106,9 @@ jspb.ExtensionFieldInfo = function(fieldNumber, fieldName, ctor, toObjectFn,
/**
* Stores binary-related information for a single extension field.
* @param {!jspb.ExtensionFieldInfo<T>} fieldInfo
- * @param {!function(number,?)} binaryReaderFn
- * @param {!function(number,?)|function(number,?,?,?,?,?)} binaryWriterFn
+ * @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
@@ -141,6 +142,21 @@ jspb.ExtensionFieldInfo.prototype.isMessageType = function() {
/**
* 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
*/
@@ -524,7 +540,7 @@ jspb.Message.toObjectExtension = function(proto, obj, extensions,
* @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(jspb.ExtensionFieldInfo) : *} getExtensionFn The proto
+ * @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,
@@ -570,10 +586,13 @@ jspb.Message.serializeBinaryExtensions = function(proto, writer, extensions,
* 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(),getFieldNumber:function():number}} reader
+ * @param {{
+ * skipField:function(this:jspb.BinaryReader),
+ * getFieldNumber:function(this:jspb.BinaryReader):number
+ * }} reader
* @param {!Object} extensions The extensions object.
- * @param {function(jspb.ExtensionFieldInfo)} getExtensionFn
- * @param {function(jspb.ExtensionFieldInfo, ?)} setExtensionFn
+ * @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) {
diff --git a/js/message_test.js b/js/message_test.js
index 2298742d..dc0ae211 100644
--- a/js/message_test.js
+++ b/js/message_test.js
@@ -40,6 +40,7 @@ goog.require('goog.userAgent');
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
diff --git a/js/package.json b/js/package.json
index dd6373de..14f54b8b 100644
--- a/js/package.json
+++ b/js/package.json
@@ -1,6 +1,6 @@
{
"name": "google-protobuf",
- "version": "3.2.0",
+ "version": "3.3.0",
"description": "Protocol Buffers for JavaScript",
"main": "google-protobuf.js",
"files": [