aboutsummaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/README.md3
-rw-r--r--js/commonjs/export.js4
-rw-r--r--js/debug.js6
-rw-r--r--js/map.js87
-rw-r--r--js/message.js91
-rw-r--r--js/message_test.js107
-rw-r--r--js/package.json2
-rw-r--r--js/proto3_test.js39
-rw-r--r--js/test.proto1
9 files changed, 192 insertions, 148 deletions
diff --git a/js/README.md b/js/README.md
index 15d48c87..f4184621 100644
--- a/js/README.md
+++ b/js/README.md
@@ -152,8 +152,7 @@ idea of how the library generally works:
// Serializes to a UInt8Array.
bytes = message.serializeBinary();
- var message2 = new MyMessage();
- message2.deserializeBinary(bytes);
+ var message2 = MyMessage.deserializeBinary(bytes);
For more examples, see the tests. You can also look at the generated code
to see what methods are defined for your generated messages.
diff --git a/js/commonjs/export.js b/js/commonjs/export.js
index a3cfbd6f..2403b1a4 100644
--- a/js/commonjs/export.js
+++ b/js/commonjs/export.js
@@ -8,13 +8,17 @@
goog.require('goog.object');
goog.require('jspb.BinaryReader');
goog.require('jspb.BinaryWriter');
+goog.require('jspb.ExtensionFieldBinaryInfo');
goog.require('jspb.ExtensionFieldInfo');
goog.require('jspb.Message');
+goog.require('jspb.Map');
+exports.Map = jspb.Map;
exports.Message = jspb.Message;
exports.BinaryReader = jspb.BinaryReader;
exports.BinaryWriter = jspb.BinaryWriter;
exports.ExtensionFieldInfo = jspb.ExtensionFieldInfo;
+exports.ExtensionFieldBinaryInfo = jspb.ExtensionFieldBinaryInfo;
// These are used by generated code but should not be used directly by clients.
exports.exportSymbol = goog.exportSymbol;
diff --git a/js/debug.js b/js/debug.js
index 3701a095..3c1ada02 100644
--- a/js/debug.js
+++ b/js/debug.js
@@ -94,8 +94,10 @@ jspb.debug.dump_ = function(thing) {
var match = /^get([A-Z]\w*)/.exec(name);
if (match && name != 'getExtension' &&
name != 'getJsPbMessageId') {
- var val = thing[name]();
- if (val != null) {
+ var has = 'has' + match[1];
+ if (!thing[has] || thing[has]())
+ {
+ var val = thing[name]();
object[jspb.debug.formatFieldName_(match[1])] = jspb.debug.dump_(val);
}
}
diff --git a/js/map.js b/js/map.js
index 821765ec..e6406a60 100644
--- a/js/map.js
+++ b/js/map.js
@@ -44,65 +44,23 @@ goog.forwardDeclare('jspb.BinaryWriter');
* on ES6 itself.
*
* This constructor should only be called from generated message code. It is not
- * intended for general use by library consumers. The callback function
- * arguments are references to methods in `BinaryReader` and `BinaryWriter`, as
- * well as constructors and reader/writer methods in submessage types if
- * appropriate, that are used for binary serialization and parsing.
+ * intended for general use by library consumers.
*
* @template K, V
*
* @param {!Array<!Array<!Object>>} arr
*
- * @param {function(this:jspb.BinaryWriter,number,K)=} opt_keyWriterFn
- * The method on BinaryWriter that writes type K to the stream.
- *
- * @param {function(this:jspb.BinaryReader):K=} opt_keyReaderFn
- * The method on BinaryReader that reads type K from the stream.
- *
- * @param {function(this:jspb.BinaryWriter,number,V)|
- * function(this:jspb.BinaryReader,V,?)=} opt_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(this:jspb.BinaryReader):V|
- * function(this:jspb.BinaryReader,V,
- * function(V,!jspb.BinaryReader))=} opt_valueReaderFn
- * The method on BinaryReader that reads type V from the stream. May be
- * readMessage, in which case the second callback arg form is used.
- *
* @param {?function(new:V)|function(new:V,?)=} opt_valueCtor
* The constructor for type V, if type V is a message type.
*
- * @param {?function(V,!jspb.BinaryWriter)=} opt_valueWriterCallback
- * The BinaryWriter serialization callback for type V, if V is a message
- * type.
- *
- * @param {?function(V,!jspb.BinaryReader)=} opt_valueReaderCallback
- * The BinaryReader parsing callback for type V, if V is a message type.
- *
* @constructor
* @struct
*/
-jspb.Map = function(
- arr, opt_keyWriterFn, opt_keyReaderFn, opt_valueWriterFn, opt_valueReaderFn,
- opt_valueCtor, opt_valueWriterCallback, opt_valueReaderCallback) {
-
+jspb.Map = function(arr, opt_valueCtor) {
/** @const @private */
this.arr_ = arr;
/** @const @private */
- this.keyWriterFn_ = opt_keyWriterFn;
- /** @const @private */
- this.keyReaderFn_ = opt_keyReaderFn;
- /** @const @private */
- this.valueWriterFn_ = opt_valueWriterFn;
- /** @const @private */
- this.valueReaderFn_ = opt_valueReaderFn;
- /** @const @private */
this.valueCtor_ = opt_valueCtor;
- /** @const @private */
- this.valueWriterCallback_ = opt_valueWriterCallback;
- /** @const @private */
- this.valueReaderCallback_ = opt_valueReaderCallback;
/** @type {!Object<string, !jspb.Map.Entry_<K,V>>} @private */
this.map_ = {};
@@ -385,19 +343,29 @@ jspb.Map.prototype.has = function(key) {
* number.
* @param {number} fieldNumber
* @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
+ * 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
+ * The BinaryWriter serialization callback for type V, if V is a message
+ * type.
*/
-jspb.Map.prototype.serializeBinary = function(fieldNumber, writer) {
+jspb.Map.prototype.serializeBinary = function(
+ fieldNumber, writer, keyWriterFn, valueWriterFn, opt_valueWriterCallback) {
var strKeys = this.stringKeys_();
strKeys.sort();
for (var i = 0; i < strKeys.length; i++) {
var entry = this.map_[strKeys[i]];
writer.beginSubMessage(fieldNumber);
- this.keyWriterFn_.call(writer, 1, entry.key);
+ keyWriterFn.call(writer, 1, entry.key);
if (this.valueCtor_) {
- this.valueWriterFn_.call(writer, 2, this.wrapEntry_(entry),
- this.valueWriterCallback_);
+ valueWriterFn.call(writer, 2, this.wrapEntry_(entry),
+ opt_valueWriterCallback);
} else {
- this.valueWriterFn_.call(writer, 2, entry.value);
+ valueWriterFn.call(writer, 2, entry.value);
}
writer.endSubMessage();
}
@@ -410,8 +378,21 @@ jspb.Map.prototype.serializeBinary = function(fieldNumber, writer) {
* when a key/value pair submessage is encountered.
* @param {!jspb.Map} map
* @param {!jspb.BinaryReader} reader
+ * @param {function(this:jspb.BinaryReader):K=} keyReaderFn
+ * The method on BinaryReader that reads type K from the stream.
+ *
+ * @param {function(this:jspb.BinaryReader):V|
+ * function(this:jspb.BinaryReader,V,
+ * function(V,!jspb.BinaryReader))=} valueReaderFn
+ * The method on BinaryReader that reads type V from the stream. May be
+ * 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.
+ *
*/
-jspb.Map.deserializeBinary = function(map, reader) {
+jspb.Map.deserializeBinary = function(map, reader, keyReaderFn, valueReaderFn,
+ opt_valueReaderCallback) {
var key = undefined;
var value = undefined;
@@ -422,14 +403,14 @@ jspb.Map.deserializeBinary = function(map, reader) {
var field = reader.getFieldNumber();
if (field == 1) {
// Key.
- key = map.keyReaderFn_.call(reader);
+ key = keyReaderFn.call(reader);
} else if (field == 2) {
// Value.
if (map.valueCtor_) {
value = new map.valueCtor_();
- map.valueReaderFn_.call(reader, value, map.valueReaderCallback_);
+ valueReaderFn.call(reader, value, opt_valueReaderCallback);
} else {
- value = map.valueReaderFn_.call(reader);
+ value = valueReaderFn.call(reader);
}
}
}
diff --git a/js/message.js b/js/message.js
index 3863bac0..631ebe69 100644
--- a/js/message.js
+++ b/js/message.js
@@ -34,6 +34,7 @@
* @author mwr@google.com (Mark Rawling)
*/
+goog.provide('jspb.ExtensionFieldBinaryInfo');
goog.provide('jspb.ExtensionFieldInfo');
goog.provide('jspb.Message');
@@ -84,19 +85,12 @@ goog.forwardDeclare('xid.String');
* @param {?function(new: jspb.Message, Array=)} ctor
* @param {?function((boolean|undefined),!jspb.Message):!Object} toObjectFn
* @param {number} isRepeated
- * @param {?function(number,?)=} opt_binaryReaderFn
- * @param {?function(number,?)|function(number,?,?,?,?,?)=} opt_binaryWriterFn
- * @param {?function(?,?)=} opt_binaryMessageSerializeFn
- * @param {?function(?,?)=} opt_binaryMessageDeserializeFn
- * @param {?boolean=} opt_isPacked
* @constructor
* @struct
* @template T
*/
jspb.ExtensionFieldInfo = function(fieldNumber, fieldName, ctor, toObjectFn,
- isRepeated, opt_binaryReaderFn, opt_binaryWriterFn,
- opt_binaryMessageSerializeFn, opt_binaryMessageDeserializeFn,
- opt_isPacked) {
+ isRepeated) {
/** @const */
this.fieldIndex = fieldNumber;
/** @const */
@@ -106,20 +100,37 @@ jspb.ExtensionFieldInfo = function(fieldNumber, fieldName, ctor, toObjectFn,
/** @const */
this.toObjectFn = toObjectFn;
/** @const */
- this.binaryReaderFn = opt_binaryReaderFn;
+ this.isRepeated = isRepeated;
+};
+
+/**
+ * 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
+ * @constructor
+ * @struct
+ * @template T
+ */
+jspb.ExtensionFieldBinaryInfo = function(fieldInfo, binaryReaderFn, binaryWriterFn,
+ binaryMessageSerializeFn, binaryMessageDeserializeFn, isPacked) {
+ /** @const */
+ this.fieldInfo = fieldInfo;
/** @const */
- this.binaryWriterFn = opt_binaryWriterFn;
+ this.binaryReaderFn = binaryReaderFn;
/** @const */
- this.binaryMessageSerializeFn = opt_binaryMessageSerializeFn;
+ this.binaryWriterFn = binaryWriterFn;
/** @const */
- this.binaryMessageDeserializeFn = opt_binaryMessageDeserializeFn;
+ this.binaryMessageSerializeFn = binaryMessageSerializeFn;
/** @const */
- this.isRepeated = isRepeated;
+ this.binaryMessageDeserializeFn = binaryMessageDeserializeFn;
/** @const */
- this.isPacked = opt_isPacked;
+ this.isPacked = isPacked;
};
-
/**
* @return {boolean} Does this field represent a sub Message?
*/
@@ -491,11 +502,13 @@ jspb.Message.toObjectExtension = function(proto, obj, extensions,
jspb.Message.serializeBinaryExtensions = function(proto, writer, extensions,
getExtensionFn) {
for (var fieldNumber in extensions) {
- var fieldInfo = extensions[fieldNumber];
+ var binaryFieldInfo = extensions[fieldNumber];
+ var fieldInfo = binaryFieldInfo.fieldInfo;
+
// The old codegen doesn't add the extra fields to ExtensionFieldInfo, so we
// need to gracefully error-out here rather than produce a null dereference
// below.
- if (!fieldInfo.binaryWriterFn) {
+ if (!binaryFieldInfo.binaryWriterFn) {
throw new Error('Message extension present that was generated ' +
'without binary serialization support');
}
@@ -508,16 +521,17 @@ jspb.Message.serializeBinaryExtensions = function(proto, writer, extensions,
// message may require binary support, so we can *only* catch this error
// here, at runtime (and this decoupled codegen is the whole point of
// extensions!).
- if (fieldInfo.binaryMessageSerializeFn) {
- fieldInfo.binaryWriterFn.call(writer, fieldInfo.fieldIndex,
- value, fieldInfo.binaryMessageSerializeFn);
+ if (binaryFieldInfo.binaryMessageSerializeFn) {
+ binaryFieldInfo.binaryWriterFn.call(writer, fieldInfo.fieldIndex,
+ value, binaryFieldInfo.binaryMessageSerializeFn);
} else {
throw new Error('Message extension present holding submessage ' +
'without binary support enabled, and message is ' +
'being serialized to binary format');
}
} else {
- fieldInfo.binaryWriterFn.call(writer, fieldInfo.fieldIndex, value);
+ binaryFieldInfo.binaryWriterFn.call(
+ writer, fieldInfo.fieldIndex, value);
}
}
}
@@ -535,12 +549,13 @@ jspb.Message.serializeBinaryExtensions = function(proto, writer, extensions,
*/
jspb.Message.readBinaryExtension = function(msg, reader, extensions,
getExtensionFn, setExtensionFn) {
- var fieldInfo = extensions[reader.getFieldNumber()];
- if (!fieldInfo) {
+ var binaryFieldInfo = extensions[reader.getFieldNumber()];
+ var fieldInfo = binaryFieldInfo.fieldInfo;
+ if (!binaryFieldInfo) {
reader.skipField();
return;
}
- if (!fieldInfo.binaryReaderFn) {
+ if (!binaryFieldInfo.binaryReaderFn) {
throw new Error('Deserializing extension whose generated code does not ' +
'support binary format');
}
@@ -548,14 +563,14 @@ jspb.Message.readBinaryExtension = function(msg, reader, extensions,
var value;
if (fieldInfo.isMessageType()) {
value = new fieldInfo.ctor();
- fieldInfo.binaryReaderFn.call(
- reader, value, fieldInfo.binaryMessageDeserializeFn);
+ binaryFieldInfo.binaryReaderFn.call(
+ reader, value, binaryFieldInfo.binaryMessageDeserializeFn);
} else {
// All other types.
- value = fieldInfo.binaryReaderFn.call(reader);
+ value = binaryFieldInfo.binaryReaderFn.call(reader);
}
- if (fieldInfo.isRepeated && !fieldInfo.isPacked) {
+ if (fieldInfo.isRepeated && !binaryFieldInfo.isPacked) {
var currentList = getExtensionFn.call(msg, fieldInfo);
if (!currentList) {
setExtensionFn.call(msg, fieldInfo, [value]);
@@ -747,29 +762,16 @@ jspb.Message.getFieldProto3 = function(msg, fieldNumber, defaultValue) {
* of serialization/parsing callbacks (which are required by the map at
* construction time, and the map may be constructed here).
*
- * The below callbacks are used to allow the map to serialize and parse its
- * binary wire format data. Their purposes are described in more detail in
- * `jspb.Map`'s constructor documentation.
- *
* @template K, V
* @param {!jspb.Message} msg
* @param {number} fieldNumber
* @param {boolean|undefined} noLazyCreate
* @param {?=} opt_valueCtor
- * @param {function(number,K)=} opt_keyWriterFn
- * @param {function():K=} opt_keyReaderFn
- * @param {function(number,V)|function(number,V,?)|
- * function(number,V,?,?,?,?)=} opt_valueWriterFn
- * @param {function():V|
- * function(V,function(?,?))=} opt_valueReaderFn
- * @param {function(?,?)|function(?,?,?,?,?)=} opt_valueWriterCallback
- * @param {function(?,?)=} opt_valueReaderCallback
* @return {!jspb.Map<K, V>|undefined}
* @protected
*/
jspb.Message.getMapField = function(msg, fieldNumber, noLazyCreate,
- opt_valueCtor, opt_keyWriterFn, opt_keyReaderFn, opt_valueWriterFn,
- opt_valueReaderFn, opt_valueWriterCallback, opt_valueReaderCallback) {
+ opt_valueCtor) {
if (!msg.wrappers_) {
msg.wrappers_ = {};
}
@@ -787,10 +789,7 @@ jspb.Message.getMapField = function(msg, fieldNumber, noLazyCreate,
}
return msg.wrappers_[fieldNumber] =
new jspb.Map(
- /** @type {!Array<!Array<!Object>>} */ (arr),
- opt_keyWriterFn, opt_keyReaderFn, opt_valueWriterFn,
- opt_valueReaderFn, opt_valueCtor, opt_valueWriterCallback,
- opt_valueReaderCallback);
+ /** @type {!Array<!Array<!Object>>} */ (arr), opt_valueCtor);
}
};
diff --git a/js/message_test.js b/js/message_test.js
index 0b0c0172..b7791431 100644
--- a/js/message_test.js
+++ b/js/message_test.js
@@ -215,6 +215,10 @@ describe('Message test suite', function() {
assertEquals(true, response.getBoolField());
assertEquals(11, response.getIntField());
assertEquals(13, response.getEnumField());
+ assertFalse(response.hasStringField());
+ assertFalse(response.hasBoolField());
+ assertFalse(response.hasIntField());
+ assertFalse(response.hasEnumField());
// Test with null values, as would be returned by a JSON serializer.
response = makeDefault([null, null, null, null]);
@@ -222,6 +226,10 @@ describe('Message test suite', function() {
assertEquals(true, response.getBoolField());
assertEquals(11, response.getIntField());
assertEquals(13, response.getEnumField());
+ assertFalse(response.hasStringField());
+ assertFalse(response.hasBoolField());
+ assertFalse(response.hasIntField());
+ assertFalse(response.hasEnumField());
// Test with false-like values.
response = makeDefault(['', false, 0, 0]);
@@ -229,6 +237,10 @@ describe('Message test suite', function() {
assertEquals(false, response.getBoolField());
assertEquals(true, response.getIntField() == 0);
assertEquals(true, response.getEnumField() == 0);
+ assertTrue(response.hasStringField());
+ assertTrue(response.hasBoolField());
+ assertTrue(response.hasIntField());
+ assertTrue(response.hasEnumField());
// Test that clearing the values reverts them to the default state.
response = makeDefault(['blah', false, 111, 77]);
@@ -238,6 +250,10 @@ describe('Message test suite', function() {
assertEquals(true, response.getBoolField());
assertEquals(11, response.getIntField());
assertEquals(13, response.getEnumField());
+ assertFalse(response.hasStringField());
+ assertFalse(response.hasBoolField());
+ assertFalse(response.hasIntField());
+ assertFalse(response.hasEnumField());
// Test that setFoo(null) clears the values.
response = makeDefault(['blah', false, 111, 77]);
@@ -247,6 +263,10 @@ describe('Message test suite', function() {
assertEquals(true, response.getBoolField());
assertEquals(11, response.getIntField());
assertEquals(13, response.getEnumField());
+ assertFalse(response.hasStringField());
+ assertFalse(response.hasBoolField());
+ assertFalse(response.hasIntField());
+ assertFalse(response.hasEnumField());
});
it('testMessageRegistration', function() {
@@ -256,9 +276,6 @@ describe('Message test suite', function() {
});
it('testClearFields', function() {
- // We don't set 'proper' defaults, rather, bools, strings,
- // etc, are cleared to undefined or null and take on the Javascript
- // meaning for that value. Repeated fields are set to [] when cleared.
var data = ['str', true, [11], [[22], [33]], ['s1', 's2']];
var foo = new proto.jspb.test.OptionalFields(data);
foo.clearAString();
@@ -266,9 +283,11 @@ describe('Message test suite', function() {
foo.clearANestedMessage();
foo.clearARepeatedMessageList();
foo.clearARepeatedStringList();
- assertUndefined(foo.getAString());
- assertUndefined(foo.getABool());
+ assertEquals('', foo.getAString());
+ assertEquals(false, foo.getABool());
assertUndefined(foo.getANestedMessage());
+ assertFalse(foo.hasAString());
+ assertFalse(foo.hasABool());
assertObjectEquals([], foo.getARepeatedMessageList());
assertObjectEquals([], foo.getARepeatedStringList());
// NOTE: We want the missing fields in 'expected' to be undefined,
@@ -288,9 +307,11 @@ describe('Message test suite', function() {
foo.setANestedMessage(null);
foo.setARepeatedMessageList(null);
foo.setARepeatedStringList(null);
- assertNull(foo.getAString());
- assertNull(foo.getABool());
+ assertEquals('', foo.getAString());
+ assertEquals(false, foo.getABool());
assertNull(foo.getANestedMessage());
+ assertFalse(foo.hasAString());
+ assertFalse(foo.hasABool());
assertObjectEquals([], foo.getARepeatedMessageList());
assertObjectEquals([], foo.getARepeatedStringList());
assertObjectEquals([null, null, null, [], []], foo.toArray());
@@ -304,9 +325,11 @@ describe('Message test suite', function() {
foo.setANestedMessage(undefined);
foo.setARepeatedMessageList(undefined);
foo.setARepeatedStringList(undefined);
- assertUndefined(foo.getAString());
- assertUndefined(foo.getABool());
+ assertEquals('', foo.getAString());
+ assertEquals(false, foo.getABool());
assertUndefined(foo.getANestedMessage());
+ assertFalse(foo.hasAString());
+ assertFalse(foo.hasABool());
assertObjectEquals([], foo.getARepeatedMessageList());
assertObjectEquals([], foo.getARepeatedStringList());
expected = [,,, [], []];
@@ -320,9 +343,9 @@ describe('Message test suite', function() {
{1000: 'unique'}]);
var diff = /** @type {proto.jspb.test.HasExtensions} */
(jspb.Message.difference(p1, p2));
- assertUndefined(diff.getStr1());
+ assertEquals('', diff.getStr1());
assertEquals('what', diff.getStr2());
- assertUndefined(diff.getStr3());
+ assertEquals('', diff.getStr3());
assertEquals('unique', diff.extensionObject_[1000]);
});
@@ -780,7 +803,7 @@ describe('Message test suite', function() {
var message = new proto.jspb.test.TestMessageWithOneof([,, 'x']);
assertEquals('x', message.getPone());
- assertUndefined(message.getPthree());
+ assertEquals('', message.getPthree());
assertEquals(
proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
message.getPartialOneofCase());
@@ -789,7 +812,7 @@ describe('Message test suite', function() {
it('testKeepsLastWireValueSetInUnion_multipleValues', function() {
var message = new proto.jspb.test.TestMessageWithOneof([,, 'x',, 'y']);
- assertUndefined('x', message.getPone());
+ assertEquals('', message.getPone());
assertEquals('y', message.getPthree());
assertEquals(
proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE,
@@ -798,35 +821,47 @@ describe('Message test suite', function() {
it('testSettingOneofFieldClearsOthers', function() {
var message = new proto.jspb.test.TestMessageWithOneof;
- assertUndefined(message.getPone());
- assertUndefined(message.getPthree());
+ assertEquals('', message.getPone());
+ assertEquals('', message.getPthree());
+ assertFalse(message.hasPone());
+ assertFalse(message.hasPthree());
message.setPone('hi');
assertEquals('hi', message.getPone());
- assertUndefined(message.getPthree());
+ assertEquals('', message.getPthree());
+ assertTrue(message.hasPone());
+ assertFalse(message.hasPthree());
message.setPthree('bye');
- assertUndefined(message.getPone());
+ assertEquals('', message.getPone());
assertEquals('bye', message.getPthree());
+ assertFalse(message.hasPone());
+ assertTrue(message.hasPthree());
});
it('testSettingOneofFieldDoesNotClearFieldsFromOtherUnions', function() {
var other = new proto.jspb.test.TestMessageWithOneof;
var message = new proto.jspb.test.TestMessageWithOneof;
- assertUndefined(message.getPone());
- assertUndefined(message.getPthree());
+ assertEquals('', message.getPone());
+ assertEquals('', message.getPthree());
assertUndefined(message.getRone());
+ assertFalse(message.hasPone());
+ assertFalse(message.hasPthree());
message.setPone('hi');
message.setRone(other);
assertEquals('hi', message.getPone());
- assertUndefined(message.getPthree());
+ assertEquals('', message.getPthree());
assertEquals(other, message.getRone());
+ assertTrue(message.hasPone());
+ assertFalse(message.hasPthree());
message.setPthree('bye');
- assertUndefined(message.getPone());
+ assertEquals('', message.getPone());
assertEquals('bye', message.getPthree());
assertEquals(other, message.getRone());
+ assertFalse(message.hasPone());
+ assertTrue(message.hasPthree());
});
it('testUnsetsOneofCaseWhenFieldIsCleared', function() {
@@ -851,7 +886,7 @@ describe('Message test suite', function() {
it('testMessageWithDefaultOneofValues', function() {
var message = new proto.jspb.test.TestMessageWithOneof;
assertEquals(1234, message.getAone());
- assertUndefined(message.getAtwo());
+ assertEquals(0, message.getAtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofACase
.DEFAULT_ONEOF_A_NOT_SET,
@@ -859,7 +894,7 @@ describe('Message test suite', function() {
message.setAone(567);
assertEquals(567, message.getAone());
- assertUndefined(message.getAtwo());
+ assertEquals(0, message.getAtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.AONE,
message.getDefaultOneofACase());
@@ -873,7 +908,7 @@ describe('Message test suite', function() {
message.clearAtwo();
assertEquals(1234, message.getAone());
- assertUndefined(message.getAtwo());
+ assertEquals(0, message.getAtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofACase
.DEFAULT_ONEOF_A_NOT_SET,
@@ -882,8 +917,10 @@ describe('Message test suite', function() {
it('testMessageWithDefaultOneofValues_defaultNotOnFirstField', function() {
var message = new proto.jspb.test.TestMessageWithOneof;
- assertUndefined(message.getBone());
+ assertEquals(0, message.getBone());
assertEquals(1234, message.getBtwo());
+ assertFalse(message.hasBone());
+ assertFalse(message.hasBtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase
.DEFAULT_ONEOF_B_NOT_SET,
@@ -892,19 +929,25 @@ describe('Message test suite', function() {
message.setBone(2);
assertEquals(2, message.getBone());
assertEquals(1234, message.getBtwo());
+ assertTrue(message.hasBone());
+ assertFalse(message.hasBtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE,
message.getDefaultOneofBCase());
message.setBtwo(3);
- assertUndefined(message.getBone());
+ assertEquals(0, message.getBone());
+ assertFalse(message.hasBone());
+ assertTrue(message.hasBtwo());
assertEquals(3, message.getBtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
message.getDefaultOneofBCase());
message.clearBtwo();
- assertUndefined(message.getBone());
+ assertEquals(0, message.getBone());
+ assertFalse(message.hasBone());
+ assertFalse(message.hasBtwo());
assertEquals(1234, message.getBtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase
@@ -916,7 +959,7 @@ describe('Message test suite', function() {
var message =
new proto.jspb.test.TestMessageWithOneof(new Array(9).concat(567));
assertEquals(567, message.getAone());
- assertUndefined(message.getAtwo());
+ assertEquals(0, message.getAtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.AONE,
message.getDefaultOneofACase());
@@ -952,7 +995,7 @@ describe('Message test suite', function() {
message =
new proto.jspb.test.TestMessageWithOneof(new Array(12).concat(890));
- assertUndefined(message.getBone());
+ assertEquals(0, message.getBone());
assertEquals(890, message.getBtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
@@ -960,7 +1003,7 @@ describe('Message test suite', function() {
message = new proto.jspb.test.TestMessageWithOneof(
new Array(11).concat(567, 890));
- assertUndefined(message.getBone());
+ assertEquals(0, message.getBone());
assertEquals(890, message.getBtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
@@ -977,7 +1020,7 @@ describe('Message test suite', function() {
var other = new proto.jspb.test.TestMessageWithOneof;
message.setRone(other);
assertEquals(other, message.getRone());
- assertUndefined(message.getRtwo());
+ assertEquals('', message.getRtwo());
assertEquals(
proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.RONE,
message.getRecursiveOneofCase());
@@ -995,7 +1038,7 @@ describe('Message test suite', function() {
var message = new proto.jspb.test.TestMessageWithOneof;
message.setPone('x');
assertEquals('x', message.getPone());
- assertUndefined(message.getPthree());
+ assertEquals('', message.getPthree());
assertEquals(
proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
message.getPartialOneofCase());
diff --git a/js/package.json b/js/package.json
index 657b08bd..3f51d96b 100644
--- a/js/package.json
+++ b/js/package.json
@@ -1,6 +1,6 @@
{
"name": "google-protobuf",
- "version": "3.0.0-alpha.6.2",
+ "version": "3.0.0",
"description": "Protocol Buffers for JavaScript",
"main": "google-protobuf.js",
"files": [
diff --git a/js/proto3_test.js b/js/proto3_test.js
index 4dd7790f..fab0fd44 100644
--- a/js/proto3_test.js
+++ b/js/proto3_test.js
@@ -221,37 +221,52 @@ describe('proto3Test', function() {
it('testOneofs', function() {
var msg = new proto.jspb.test.TestProto3();
- assertEquals(msg.getOneofUint32(), undefined);
+ assertEquals(msg.getOneofUint32(), 0);
assertEquals(msg.getOneofForeignMessage(), undefined);
- assertEquals(msg.getOneofString(), undefined);
- assertEquals(msg.getOneofBytes(), undefined);
+ assertEquals(msg.getOneofString(), '');
+ assertEquals(msg.getOneofBytes(), '');
+ assertFalse(msg.hasOneofUint32());
+ assertFalse(msg.hasOneofString());
+ assertFalse(msg.hasOneofBytes());
msg.setOneofUint32(42);
assertEquals(msg.getOneofUint32(), 42);
assertEquals(msg.getOneofForeignMessage(), undefined);
- assertEquals(msg.getOneofString(), undefined);
- assertEquals(msg.getOneofBytes(), undefined);
+ assertEquals(msg.getOneofString(), '');
+ assertEquals(msg.getOneofBytes(), '');
+ assertTrue(msg.hasOneofUint32());
+ assertFalse(msg.hasOneofString());
+ assertFalse(msg.hasOneofBytes());
var submsg = new proto.jspb.test.ForeignMessage();
msg.setOneofForeignMessage(submsg);
- assertEquals(msg.getOneofUint32(), undefined);
+ assertEquals(msg.getOneofUint32(), 0);
assertEquals(msg.getOneofForeignMessage(), submsg);
- assertEquals(msg.getOneofString(), undefined);
- assertEquals(msg.getOneofBytes(), undefined);
+ assertEquals(msg.getOneofString(), '');
+ assertEquals(msg.getOneofBytes(), '');
+ assertFalse(msg.hasOneofUint32());
+ assertFalse(msg.hasOneofString());
+ assertFalse(msg.hasOneofBytes());
msg.setOneofString('hello');
- assertEquals(msg.getOneofUint32(), undefined);
+ assertEquals(msg.getOneofUint32(), 0);
assertEquals(msg.getOneofForeignMessage(), undefined);
assertEquals(msg.getOneofString(), 'hello');
- assertEquals(msg.getOneofBytes(), undefined);
+ assertEquals(msg.getOneofBytes(), '');
+ assertFalse(msg.hasOneofUint32());
+ assertTrue(msg.hasOneofString());
+ assertFalse(msg.hasOneofBytes());
msg.setOneofBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
- assertEquals(msg.getOneofUint32(), undefined);
+ assertEquals(msg.getOneofUint32(), 0);
assertEquals(msg.getOneofForeignMessage(), undefined);
- assertEquals(msg.getOneofString(), undefined);
+ assertEquals(msg.getOneofString(), '');
assertEquals(msg.getOneofBytes_asB64(),
goog.crypt.base64.encodeString('\u00FF\u00FF'));
+ assertFalse(msg.hasOneofUint32());
+ assertFalse(msg.hasOneofString());
+ assertTrue(msg.hasOneofBytes());
});
diff --git a/js/test.proto b/js/test.proto
index cf2eafef..937ffb89 100644
--- a/js/test.proto
+++ b/js/test.proto
@@ -233,3 +233,4 @@ message TestEndsWithBytes {
optional int32 value = 1;
optional bytes data = 2;
}
+