diff options
Diffstat (limited to 'js')
-rw-r--r-- | js/README.md | 3 | ||||
-rw-r--r-- | js/commonjs/export.js | 4 | ||||
-rw-r--r-- | js/debug.js | 6 | ||||
-rw-r--r-- | js/map.js | 87 | ||||
-rw-r--r-- | js/message.js | 91 | ||||
-rw-r--r-- | js/message_test.js | 107 | ||||
-rw-r--r-- | js/package.json | 2 | ||||
-rw-r--r-- | js/proto3_test.js | 39 | ||||
-rw-r--r-- | js/test.proto | 1 |
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); } } @@ -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; } + |