aboutsummaryrefslogtreecommitdiffhomepage
path: root/js/message.js
diff options
context:
space:
mode:
authorGravatar Jisi Liu <jisi.liu@gmail.com>2017-07-18 15:38:30 -0700
committerGravatar Jisi Liu <jisi.liu@gmail.com>2017-07-18 15:38:30 -0700
commit09354db1434859a31a3c81abebcc4018d42f2715 (patch)
treeb87c7cdc2255e6c8062ab92b4082665cd698d753 /js/message.js
parent9053033a5076f82cf18b823c31f352e95e5bfd8d (diff)
Merge from Google internal for 3.4 release
Diffstat (limited to 'js/message.js')
-rw-r--r--js/message.js86
1 files changed, 53 insertions, 33 deletions
diff --git a/js/message.js b/js/message.js
index 1f6bf16b..f7dcfa96 100644
--- a/js/message.js
+++ b/js/message.js
@@ -41,7 +41,6 @@ goog.provide('jspb.Message');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.crypt.base64');
-goog.require('goog.json');
goog.require('jspb.Map');
// Not needed in compilation units that have no protos with xids.
@@ -192,8 +191,8 @@ goog.define('jspb.Message.GENERATE_FROM_OBJECT', !goog.DISALLOW_TEST_ONLY_CODE);
/**
* @define {boolean} Whether to generate toString methods for objects. Turn
- * this off if you do use toString in your project and want to trim it from
- * compiled JS.
+ * this off if you do not use toString in your project and want to trim it
+ * from the compiled JS.
*/
goog.define('jspb.Message.GENERATE_TO_STRING', true);
@@ -351,7 +350,7 @@ jspb.Message.initialize = function(
// which would otherwise go unused.
msg.arrayIndexOffset_ = messageId === 0 ? -1 : 0;
msg.array = data;
- jspb.Message.materializeExtensionObject_(msg, suggestedPivot);
+ jspb.Message.initPivotAndExtensionObject_(msg, suggestedPivot);
msg.convertedFloatingPointFields_ = {};
if (repeatedFields) {
@@ -364,6 +363,7 @@ jspb.Message.initialize = function(
jspb.Message.EMPTY_LIST_SENTINEL_ :
[]);
} else {
+ jspb.Message.maybeInitEmptyExtensionObject_(msg);
msg.extensionObject_[fieldNumber] =
msg.extensionObject_[fieldNumber] ||
(jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS ?
@@ -408,17 +408,16 @@ jspb.Message.isArray_ = function(o) {
/**
- * Ensures that the array contains an extension object if necessary.
* If the array contains an extension object in its last position, then the
- * object is kept in place and its position is used as the pivot. If not, then
- * create an extension object using suggestedPivot. If suggestedPivot is -1,
- * we don't have an extension object at all, in which case all fields are stored
- * in the array.
+ * object is kept in place and its position is used as the pivot. If not,
+ * decides the pivot of the message based on suggestedPivot without
+ * materializing the extension object.
+ *
* @param {!jspb.Message} msg The JsPb proto to modify.
* @param {number} suggestedPivot See description for initialize().
* @private
*/
-jspb.Message.materializeExtensionObject_ = function(msg, suggestedPivot) {
+jspb.Message.initPivotAndExtensionObject_ = function(msg, suggestedPivot) {
if (msg.array.length) {
var foundIndex = msg.array.length - 1;
var obj = msg.array[foundIndex];
@@ -434,26 +433,17 @@ jspb.Message.materializeExtensionObject_ = function(msg, suggestedPivot) {
return;
}
}
- // This complexity exists because we keep all extension fields in the
- // extensionObject_ regardless of proto field number. Changing this would
- // simplify the code here, but it would require changing the serialization
- // format from the server, which is not backwards compatible.
- // TODO(jshneier): Should we just treat extension fields the same as
- // non-extension fields, and select whether they appear in the object or in
- // the array purely based on tag number? This would allow simplifying all the
- // get/setExtension logic, but it would require the breaking change described
- // above.
+
if (suggestedPivot > -1) {
msg.pivot_ = suggestedPivot;
- var pivotIndex = jspb.Message.getIndex_(msg, suggestedPivot);
- if (!jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS) {
- msg.extensionObject_ = msg.array[pivotIndex] = {};
- } else {
- // Initialize to null to avoid changing the shape of the proto when it
- // gets eventually set.
- msg.extensionObject_ = null;
- }
+ // Avoid changing the shape of the proto with an empty extension object by
+ // deferring the materialization of the extension object until the first
+ // time a field set into it (may be due to getting a repeated proto field
+ // from it, in which case a new empty array is set into it at first).
+ msg.extensionObject_ = null;
} else {
+ // suggestedPivot is -1, which means that we don't have an extension object
+ // at all, in which case all fields are stored in the array.
msg.pivot_ = Number.MAX_VALUE;
}
};
@@ -513,7 +503,7 @@ jspb.Message.toObjectExtension = function(proto, obj, extensions,
for (var fieldNumber in extensions) {
var fieldInfo = extensions[fieldNumber];
var value = getExtensionFn.call(proto, fieldInfo);
- if (goog.isDefAndNotNull(value)) {
+ if (value != null) {
for (var name in fieldInfo.fieldName) {
if (fieldInfo.fieldName.hasOwnProperty(name)) {
break; // the compiled field name
@@ -557,7 +547,7 @@ jspb.Message.serializeBinaryExtensions = function(proto, writer, extensions,
'without binary serialization support');
}
var value = getExtensionFn.call(proto, fieldInfo);
- if (goog.isDefAndNotNull(value)) {
+ if (value != null) {
if (fieldInfo.isMessageType()) {
// If the message type of the extension was generated without binary
// support, there may not be a binary message serializer function, and
@@ -647,6 +637,9 @@ jspb.Message.getField = function(msg, fieldNumber) {
}
return val;
} else {
+ if (!msg.extensionObject_) {
+ return undefined;
+ }
var val = msg.extensionObject_[fieldNumber];
if (val === jspb.Message.EMPTY_LIST_SENTINEL_) {
return msg.extensionObject_[fieldNumber] = [];
@@ -657,6 +650,32 @@ jspb.Message.getField = function(msg, fieldNumber) {
/**
+ * Gets the value of a non-extension repeated field.
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @return {!Array}
+ * The field's value.
+ * @protected
+ */
+jspb.Message.getRepeatedField = function(msg, fieldNumber) {
+ if (fieldNumber < msg.pivot_) {
+ var index = jspb.Message.getIndex_(msg, fieldNumber);
+ var val = msg.array[index];
+ if (val === jspb.Message.EMPTY_LIST_SENTINEL_) {
+ return msg.array[index] = [];
+ }
+ return val;
+ }
+
+ var val = msg.extensionObject_[fieldNumber];
+ if (val === jspb.Message.EMPTY_LIST_SENTINEL_) {
+ return msg.extensionObject_[fieldNumber] = [];
+ }
+ return val;
+};
+
+
+/**
* Gets the value of an optional float or double field.
* @param {!jspb.Message} msg A jspb proto.
* @param {number} fieldNumber The field number.
@@ -678,7 +697,7 @@ jspb.Message.getOptionalFloatingPointField = function(msg, fieldNumber) {
* @protected
*/
jspb.Message.getRepeatedFloatingPointField = function(msg, fieldNumber) {
- var values = jspb.Message.getField(msg, fieldNumber);
+ var values = jspb.Message.getRepeatedField(msg, fieldNumber);
if (!msg.convertedFloatingPointFields_) {
msg.convertedFloatingPointFields_ = {};
}
@@ -864,6 +883,7 @@ jspb.Message.setField = function(msg, fieldNumber, value) {
if (fieldNumber < msg.pivot_) {
msg.array[jspb.Message.getIndex_(msg, fieldNumber)] = value;
} else {
+ jspb.Message.maybeInitEmptyExtensionObject_(msg);
msg.extensionObject_[fieldNumber] = value;
}
};
@@ -878,7 +898,7 @@ jspb.Message.setField = function(msg, fieldNumber, value) {
* @protected
*/
jspb.Message.addToRepeatedField = function(msg, fieldNumber, value, opt_index) {
- var arr = jspb.Message.getField(msg, fieldNumber);
+ var arr = jspb.Message.getRepeatedField(msg, fieldNumber);
if (opt_index != undefined) {
arr.splice(opt_index, 0, value);
} else {
@@ -1006,7 +1026,7 @@ jspb.Message.wrapRepeatedField_ = function(msg, ctor, fieldNumber) {
msg.wrappers_ = {};
}
if (!msg.wrappers_[fieldNumber]) {
- var data = jspb.Message.getField(msg, fieldNumber);
+ var data = jspb.Message.getRepeatedField(msg, fieldNumber);
for (var wrappers = [], i = 0; i < data.length; i++) {
wrappers[i] = new ctor(data[i]);
}
@@ -1101,7 +1121,7 @@ jspb.Message.addToRepeatedWrapperField = function(
wrapperArray = msg.wrappers_[fieldNumber] = [];
}
var insertedValue = value ? value : new ctor();
- var array = jspb.Message.getField(msg, fieldNumber);
+ var array = jspb.Message.getRepeatedField(msg, fieldNumber);
if (index != undefined) {
wrapperArray.splice(index, 0, insertedValue);
array.splice(index, 0, insertedValue.toArray());