Skip to content

Commit afc5eb3

Browse files
author
Adam Cozzette
committed
Integrated internal changes from Google
This includes all internal changes from around May 20 to now.
1 parent 0070984 commit afc5eb3

File tree

9 files changed

+492
-141
lines changed

9 files changed

+492
-141
lines changed

binary/constants.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,8 @@ jspb.ReaderFunction;
141141

142142
/**
143143
* A writer function serializes a message to a BinaryWriter.
144-
* @typedef {!function(!jspb.Message, !jspb.BinaryWriter):void |
145-
* !function(!jspb.ConstBinaryMessage, !jspb.BinaryWriter):void}
144+
* @typedef {function((!jspb.Message|!jspb.ConstBinaryMessage),
145+
* !jspb.BinaryWriter):void}
146146
*/
147147
jspb.WriterFunction;
148148

binary/decoder_test.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,8 @@ function doTestSignedValue(readValue,
147147
describe('binaryDecoderTest', function() {
148148
/**
149149
* Tests the decoder instance cache.
150-
* @suppress {visibility}
151150
*/
152-
it('testInstanceCache', function() {
151+
it('testInstanceCache', /** @suppress {visibility} */ function() {
153152
// Empty the instance caches.
154153
jspb.BinaryDecoder.instanceCache_ = [];
155154

binary/reader_test.js

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,8 @@ goog.require('jspb.BinaryWriter');
5252
describe('binaryReaderTest', function() {
5353
/**
5454
* Tests the reader instance cache.
55-
* @suppress {visibility}
5655
*/
57-
it('testInstanceCaches', function() {
56+
it('testInstanceCaches', /** @suppress {visibility} */ function() {
5857
var writer = new jspb.BinaryWriter();
5958
var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
6059
writer.writeMessage(1, dummyMessage, goog.nullFunction);
@@ -131,9 +130,8 @@ describe('binaryReaderTest', function() {
131130

132131
/**
133132
* Verifies that misuse of the reader class triggers assertions.
134-
* @suppress {checkTypes|visibility}
135133
*/
136-
it('testReadErrors', function() {
134+
it('testReadErrors', /** @suppress {checkTypes|visibility} */ function() {
137135
// Calling readMessage on a non-delimited field should trigger an
138136
// assertion.
139137
var reader = jspb.BinaryReader.alloc([8, 1]);
@@ -200,7 +198,7 @@ describe('binaryReaderTest', function() {
200198
* @private
201199
* @suppress {missingProperties}
202200
*/
203-
function doTestUnsignedField_(readField,
201+
var doTestUnsignedField_ = function(readField,
204202
writeField, epsilon, upperLimit, filter) {
205203
assertNotNull(readField);
206204
assertNotNull(writeField);
@@ -252,7 +250,7 @@ describe('binaryReaderTest', function() {
252250
* @private
253251
* @suppress {missingProperties}
254252
*/
255-
function doTestSignedField_(readField,
253+
var doTestSignedField_ = function(readField,
256254
writeField, epsilon, lowerLimit, upperLimit, filter) {
257255
var writer = new jspb.BinaryWriter();
258256

@@ -321,12 +319,12 @@ describe('binaryReaderTest', function() {
321319
* Tests fields that use varint encoding.
322320
*/
323321
it('testVarintFields', function() {
324-
assertNotNull(jspb.BinaryReader.prototype.readUint32);
325-
assertNotNull(jspb.BinaryReader.prototype.writeUint32);
326-
assertNotNull(jspb.BinaryReader.prototype.readUint64);
327-
assertNotNull(jspb.BinaryReader.prototype.writeUint64);
328-
assertNotNull(jspb.BinaryReader.prototype.readBool);
329-
assertNotNull(jspb.BinaryReader.prototype.writeBool);
322+
assertNotUndefined(jspb.BinaryReader.prototype.readUint32);
323+
assertNotUndefined(jspb.BinaryWriter.prototype.writeUint32);
324+
assertNotUndefined(jspb.BinaryReader.prototype.readUint64);
325+
assertNotUndefined(jspb.BinaryWriter.prototype.writeUint64);
326+
assertNotUndefined(jspb.BinaryReader.prototype.readBool);
327+
assertNotUndefined(jspb.BinaryWriter.prototype.writeBool);
330328
doTestUnsignedField_(
331329
jspb.BinaryReader.prototype.readUint32,
332330
jspb.BinaryWriter.prototype.writeUint32,
@@ -369,8 +367,7 @@ describe('binaryReaderTest', function() {
369367
var bytesCount = (hexString.length + 1) / 3;
370368
var bytes = new Uint8Array(bytesCount);
371369
for (var i = 0; i < bytesCount; i++) {
372-
byte = parseInt(hexString.substring(i * 3, i * 3 + 2), 16);
373-
bytes[i] = byte;
370+
bytes[i] = parseInt(hexString.substring(i * 3, i * 3 + 2), 16);
374371
}
375372
var reader = jspb.BinaryReader.alloc(bytes);
376373
reader.nextField();

binary/writer.js

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -717,11 +717,19 @@ jspb.BinaryWriter.prototype.writeBytes = function(field, value) {
717717

718718
/**
719719
* Writes a message to the buffer.
720-
* @template MessageType
721720
* @param {number} field The field number.
722721
* @param {?MessageType} value The message to write.
723-
* @param {!jspb.WriterFunction} writerCallback Will be invoked with the value
724-
* to write and the writer to write it with.
722+
* @param {function(MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback
723+
* Will be invoked with the value to write and the writer to write it with.
724+
* @template MessageType
725+
* Use go/closure-ttl to declare a non-nullable version of MessageType. Replace
726+
* the null in blah|null with none. This is necessary because the compiler will
727+
* infer MessageType to be nullable if the value parameter is nullable.
728+
* @template MessageTypeNonNull :=
729+
* cond(isUnknown(MessageType), unknown(),
730+
* mapunion(MessageType, (X) =>
731+
* cond(eq(X, 'null'), none(), X)))
732+
* =:
725733
*/
726734
jspb.BinaryWriter.prototype.writeMessage = function(
727735
field, value, writerCallback) {
@@ -735,12 +743,20 @@ jspb.BinaryWriter.prototype.writeMessage = function(
735743
/**
736744
* Writes a group message to the buffer.
737745
*
738-
* @template MessageType
739746
* @param {number} field The field number.
740747
* @param {?MessageType} value The message to write, wrapped with START_GROUP /
741748
* END_GROUP tags. Will be a no-op if 'value' is null.
742-
* @param {!jspb.WriterFunction} writerCallback Will be invoked with the value
743-
* to write and the writer to write it with.
749+
* @param {function(MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback
750+
* Will be invoked with the value to write and the writer to write it with.
751+
* @template MessageType
752+
* Use go/closure-ttl to declare a non-nullable version of MessageType. Replace
753+
* the null in blah|null with none. This is necessary because the compiler will
754+
* infer MessageType to be nullable if the value parameter is nullable.
755+
* @template MessageTypeNonNull :=
756+
* cond(isUnknown(MessageType), unknown(),
757+
* mapunion(MessageType, (X) =>
758+
* cond(eq(X, 'null'), none(), X)))
759+
* =:
744760
*/
745761
jspb.BinaryWriter.prototype.writeGroup = function(
746762
field, value, writerCallback) {
@@ -1122,8 +1138,8 @@ jspb.BinaryWriter.prototype.writeRepeatedBytes = function(field, value) {
11221138
* @param {number} field The field number.
11231139
* @param {?Array.<MessageType>} value The array of messages to
11241140
* write.
1125-
* @param {!jspb.WriterFunction} writerCallback Will be invoked with the value
1126-
* to write and the writer to write it with.
1141+
* @param {function(MessageType, !jspb.BinaryWriter)} writerCallback
1142+
* Will be invoked with the value to write and the writer to write it with.
11271143
*/
11281144
jspb.BinaryWriter.prototype.writeRepeatedMessage = function(
11291145
field, value, writerCallback) {
@@ -1142,8 +1158,8 @@ jspb.BinaryWriter.prototype.writeRepeatedMessage = function(
11421158
* @param {number} field The field number.
11431159
* @param {?Array.<MessageType>} value The array of messages to
11441160
* write.
1145-
* @param {!jspb.WriterFunction} writerCallback Will be invoked with the value
1146-
* to write and the writer to write it with.
1161+
* @param {function(MessageType, !jspb.BinaryWriter)} writerCallback
1162+
* Will be invoked with the value to write and the writer to write it with.
11471163
*/
11481164
jspb.BinaryWriter.prototype.writeRepeatedGroup = function(
11491165
field, value, writerCallback) {

message.js

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ goog.require('goog.array');
4141
goog.require('goog.asserts');
4242
goog.require('goog.crypt.base64');
4343
goog.require('goog.json');
44+
goog.require('jspb.Map');
4445

4546
// Not needed in compilation units that have no protos with xids.
4647
goog.forwardDeclare('xid.String');
@@ -371,7 +372,8 @@ jspb.Message.materializeExtensionObject_ = function(msg, suggestedPivot) {
371372
// the object is not an array, since arrays are valid field values.
372373
// NOTE(lukestebbing): We avoid looking at .length to avoid a JIT bug
373374
// in Safari on iOS 8. See the description of CL/86511464 for details.
374-
if (obj && typeof obj == 'object' && !goog.isArray(obj)) {
375+
if (obj && typeof obj == 'object' && !goog.isArray(obj) &&
376+
!(jspb.Message.SUPPORTS_UINT8ARRAY_ && obj instanceof Uint8Array)) {
375377
msg.pivot_ = foundIndex - msg.arrayIndexOffset_;
376378
msg.extensionObject_ = obj;
377379
return;
@@ -737,6 +739,62 @@ jspb.Message.getFieldProto3 = function(msg, fieldNumber, defaultValue) {
737739
};
738740

739741

742+
/**
743+
* Gets the value of a map field, lazily creating the map container if
744+
* necessary.
745+
*
746+
* This should only be called from generated code, because it requires knowledge
747+
* of serialization/parsing callbacks (which are required by the map at
748+
* construction time, and the map may be constructed here).
749+
*
750+
* The below callbacks are used to allow the map to serialize and parse its
751+
* binary wire format data. Their purposes are described in more detail in
752+
* `jspb.Map`'s constructor documentation.
753+
*
754+
* @template K, V
755+
* @param {!jspb.Message} msg
756+
* @param {number} fieldNumber
757+
* @param {boolean|undefined} noLazyCreate
758+
* @param {?=} opt_valueCtor
759+
* @param {function(number,K)=} opt_keyWriterFn
760+
* @param {function():K=} opt_keyReaderFn
761+
* @param {function(number,V)|function(number,V,?)|
762+
* function(number,V,?,?,?,?)=} opt_valueWriterFn
763+
* @param {function():V|
764+
* function(V,function(?,?))=} opt_valueReaderFn
765+
* @param {function(?,?)|function(?,?,?,?,?)=} opt_valueWriterCallback
766+
* @param {function(?,?)=} opt_valueReaderCallback
767+
* @return {!jspb.Map<K, V>|undefined}
768+
* @protected
769+
*/
770+
jspb.Message.getMapField = function(msg, fieldNumber, noLazyCreate,
771+
opt_valueCtor, opt_keyWriterFn, opt_keyReaderFn, opt_valueWriterFn,
772+
opt_valueReaderFn, opt_valueWriterCallback, opt_valueReaderCallback) {
773+
if (!msg.wrappers_) {
774+
msg.wrappers_ = {};
775+
}
776+
// If we already have a map in the map wrappers, return that.
777+
if (fieldNumber in msg.wrappers_) {
778+
return msg.wrappers_[fieldNumber];
779+
} else if (noLazyCreate) {
780+
return undefined;
781+
} else {
782+
// Wrap the underlying elements array with a Map.
783+
var arr = jspb.Message.getField(msg, fieldNumber);
784+
if (!arr) {
785+
arr = [];
786+
jspb.Message.setField(msg, fieldNumber, arr);
787+
}
788+
return msg.wrappers_[fieldNumber] =
789+
new jspb.Map(
790+
/** @type {!Array<!Array<!Object>>} */ (arr),
791+
opt_keyWriterFn, opt_keyReaderFn, opt_valueWriterFn,
792+
opt_valueReaderFn, opt_valueCtor, opt_valueWriterCallback,
793+
opt_valueReaderCallback);
794+
}
795+
};
796+
797+
740798
/**
741799
* Sets the value of a non-extension field.
742800
* @param {!jspb.Message} msg A jspb proto.
@@ -952,13 +1010,46 @@ jspb.Message.toMap = function(
9521010
};
9531011

9541012

1013+
/**
1014+
* Syncs all map fields' contents back to their underlying arrays.
1015+
* @private
1016+
*/
1017+
jspb.Message.prototype.syncMapFields_ = function() {
1018+
// This iterates over submessage, map, and repeated fields, which is intended.
1019+
// Submessages can contain maps which also need to be synced.
1020+
//
1021+
// There is a lot of opportunity for optimization here. For example we could
1022+
// statically determine that some messages have no submessages with maps and
1023+
// optimize this method away for those just by generating one extra static
1024+
// boolean per message type.
1025+
if (this.wrappers_) {
1026+
for (var fieldNumber in this.wrappers_) {
1027+
var val = this.wrappers_[fieldNumber];
1028+
if (goog.isArray(val)) {
1029+
for (var i = 0; i < val.length; i++) {
1030+
if (val[i]) {
1031+
val[i].toArray();
1032+
}
1033+
}
1034+
} else {
1035+
// Works for submessages and maps.
1036+
if (val) {
1037+
val.toArray();
1038+
}
1039+
}
1040+
}
1041+
}
1042+
};
1043+
1044+
9551045
/**
9561046
* Returns the internal array of this proto.
9571047
* <p>Note: If you use this array to construct a second proto, the content
9581048
* would then be partially shared between the two protos.
9591049
* @return {!Array} The proto represented as an array.
9601050
*/
9611051
jspb.Message.prototype.toArray = function() {
1052+
this.syncMapFields_();
9621053
return this.array;
9631054
};
9641055

@@ -972,6 +1063,7 @@ jspb.Message.prototype.toArray = function() {
9721063
* @override
9731064
*/
9741065
jspb.Message.prototype.toString = function() {
1066+
this.syncMapFields_();
9751067
return this.array.toString();
9761068
};
9771069

@@ -1293,6 +1385,9 @@ jspb.Message.clone_ = function(obj) {
12931385
}
12941386
return clonedArray;
12951387
}
1388+
if (jspb.Message.SUPPORTS_UINT8ARRAY_ && obj instanceof Uint8Array) {
1389+
return new Uint8Array(obj);
1390+
}
12961391
var clone = {};
12971392
for (var key in obj) {
12981393
if ((o = obj[key]) != null) {

0 commit comments

Comments
 (0)