diff options
Diffstat (limited to 'js/message.js')
-rw-r--r-- | js/message.js | 154 |
1 files changed, 129 insertions, 25 deletions
diff --git a/js/message.js b/js/message.js index 631ebe69..b150722a 100644 --- a/js/message.js +++ b/js/message.js @@ -106,17 +106,17 @@ 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(?,?)=} opt_binaryMessageSerializeFn - * @param {?function(?,?)=} opt_binaryMessageDeserializeFn - * @param {?boolean=} opt_isPacked + * @param {!function(number,?)} binaryReaderFn + * @param {!function(number,?)|function(number,?,?,?,?,?)} binaryWriterFn + * @param {function(?,?)=} opt_binaryMessageSerializeFn + * @param {function(?,?)=} opt_binaryMessageDeserializeFn + * @param {boolean=} opt_isPacked * @constructor * @struct * @template T */ jspb.ExtensionFieldBinaryInfo = function(fieldInfo, binaryReaderFn, binaryWriterFn, - binaryMessageSerializeFn, binaryMessageDeserializeFn, isPacked) { + opt_binaryMessageSerializeFn, opt_binaryMessageDeserializeFn, opt_isPacked) { /** @const */ this.fieldInfo = fieldInfo; /** @const */ @@ -124,11 +124,11 @@ jspb.ExtensionFieldBinaryInfo = function(fieldInfo, binaryReaderFn, binaryWriter /** @const */ this.binaryWriterFn = binaryWriterFn; /** @const */ - this.binaryMessageSerializeFn = binaryMessageSerializeFn; + this.binaryMessageSerializeFn = opt_binaryMessageSerializeFn; /** @const */ - this.binaryMessageDeserializeFn = binaryMessageDeserializeFn; + this.binaryMessageDeserializeFn = opt_binaryMessageDeserializeFn; /** @const */ - this.isPacked = isPacked; + this.isPacked = opt_isPacked; }; /** @@ -744,7 +744,7 @@ jspb.Message.assertConsistentTypes_ = function(array) { * @return {T} The field's value. * @protected */ -jspb.Message.getFieldProto3 = function(msg, fieldNumber, defaultValue) { +jspb.Message.getFieldWithDefault = function(msg, fieldNumber, defaultValue) { var value = jspb.Message.getField(msg, fieldNumber); if (value == null) { return defaultValue; @@ -811,6 +811,24 @@ jspb.Message.setField = function(msg, fieldNumber, value) { /** + * 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.getField(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. @@ -907,6 +925,24 @@ jspb.Message.getWrapperField = function(msg, ctor, fieldNumber, opt_required) { * @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_ = {}; } @@ -917,11 +953,6 @@ jspb.Message.getRepeatedWrapperField = function(msg, ctor, fieldNumber) { } msg.wrappers_[fieldNumber] = wrappers; } - var val = msg.wrappers_[fieldNumber]; - if (val == jspb.Message.EMPTY_LIST_SENTINEL_) { - val = msg.wrappers_[fieldNumber] = []; - } - return /** @type {Array<!jspb.Message>} */ (val); }; @@ -981,6 +1012,48 @@ jspb.Message.setRepeatedWrapperField = function(msg, fieldNumber, value) { /** + * 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.getField(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. @@ -1114,32 +1187,39 @@ jspb.Message.prototype.getExtension = function(fieldInfo) { * @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) { - if (!this.wrappers_) { - this.wrappers_ = {}; + // 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_(this); + jspb.Message.maybeInitEmptyExtensionObject_(self); var fieldNumber = fieldInfo.fieldIndex; if (fieldInfo.isRepeated) { value = value || []; if (fieldInfo.isMessageType()) { - this.wrappers_[fieldNumber] = value; - this.extensionObject_[fieldNumber] = goog.array.map( + self.wrappers_[fieldNumber] = value; + self.extensionObject_[fieldNumber] = goog.array.map( /** @type {Array<jspb.Message>} */ (value), function(msg) { return msg.toArray(); }); } else { - this.extensionObject_[fieldNumber] = value; + self.extensionObject_[fieldNumber] = value; } } else { if (fieldInfo.isMessageType()) { - this.wrappers_[fieldNumber] = value; - this.extensionObject_[fieldNumber] = value ? value.toArray() : value; + self.wrappers_[fieldNumber] = value; + self.extensionObject_[fieldNumber] = value ? value.toArray() : value; } else { - this.extensionObject_[fieldNumber] = value; + self.extensionObject_[fieldNumber] = value; } } + return self; }; @@ -1308,7 +1388,30 @@ jspb.Message.compareFields = function(field1, field2) { /** - * Static clone function. NOTE: A type-safe method called "cloneMessage" exists + * 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. @@ -1429,3 +1532,4 @@ jspb.Message.registry_ = {}; * @type {!Object.<number, jspb.ExtensionFieldInfo>} */ jspb.Message.messageSetExtensions = {}; +jspb.Message.messageSetExtensionsBinary = {}; |