Integrated internal changes from Google
diff --git a/js/binary/decoder.js b/js/binary/decoder.js
index 6db28e7..313d6f3 100644
--- a/js/binary/decoder.js
+++ b/js/binary/decoder.js
@@ -47,6 +47,7 @@
 goog.provide('jspb.BinaryIterator');
 
 goog.require('goog.asserts');
+goog.require('goog.crypt');
 goog.require('jspb.utils');
 
 
diff --git a/js/binary/utils.js b/js/binary/utils.js
index 58f11b5..c706bff 100644
--- a/js/binary/utils.js
+++ b/js/binary/utils.js
@@ -38,6 +38,7 @@
 goog.provide('jspb.utils');
 
 goog.require('goog.asserts');
+goog.require('goog.crypt');
 goog.require('goog.crypt.base64');
 goog.require('goog.string');
 goog.require('jspb.BinaryConstants');
diff --git a/js/binary/utils_test.js b/js/binary/utils_test.js
index 0a2f4f0..6b481dc 100644
--- a/js/binary/utils_test.js
+++ b/js/binary/utils_test.js
@@ -36,6 +36,7 @@
  * @author aappleby@google.com (Austin Appleby)
  */
 
+goog.require('goog.crypt');
 goog.require('goog.crypt.base64');
 goog.require('goog.testing.asserts');
 goog.require('jspb.BinaryConstants');
diff --git a/js/compatibility_tests/v3.1.0/message_test.js b/js/compatibility_tests/v3.1.0/message_test.js
index b46e50d..c102378 100644
--- a/js/compatibility_tests/v3.1.0/message_test.js
+++ b/js/compatibility_tests/v3.1.0/message_test.js
@@ -643,12 +643,7 @@
 
   it('testInitialization_emptyArray', function() {
     var msg = new proto.jspb.test.HasExtensions([]);
-    if (jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS) {
-      assertArrayEquals([], msg.toArray());
-    } else {
-      // Extension object is created past all regular fields.
-      assertArrayEquals([,,, {}], msg.toArray());
-    }
+    assertArrayEquals([], msg.toArray());
   });
 
   it('testInitialization_justExtensionObject', function() {
diff --git a/js/message.js b/js/message.js
index f7dcfa9..1484229 100644
--- a/js/message.js
+++ b/js/message.js
@@ -890,6 +890,100 @@
 
 
 /**
+ * Sets the value of a non-extension integer field of a proto3
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @param {number} value New value
+ * @protected
+ */
+jspb.Message.setProto3IntField = function(msg, fieldNumber, value) {
+  jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0);
+};
+
+
+/**
+ * Sets the value of a non-extension floating point field of a proto3
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @param {number} value New value
+ * @protected
+ */
+jspb.Message.setProto3FloatField = function(msg, fieldNumber, value) {
+  jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0.0);
+};
+
+
+/**
+ * Sets the value of a non-extension boolean field of a proto3
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @param {boolean} value New value
+ * @protected
+ */
+jspb.Message.setProto3BooleanField = function(msg, fieldNumber, value) {
+  jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, false);
+};
+
+
+/**
+ * Sets the value of a non-extension String field of a proto3
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @param {string} value New value
+ * @protected
+ */
+jspb.Message.setProto3StringField = function(msg, fieldNumber, value) {
+  jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, "");
+};
+
+
+/**
+ * Sets the value of a non-extension Bytes field of a proto3
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @param {!Uint8Array|string} value New value
+ * @protected
+ */
+jspb.Message.setProto3BytesField = function(msg, fieldNumber, value) {
+  jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, "");
+};
+
+
+/**
+ * Sets the value of a non-extension enum field of a proto3
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @param {number} value New value
+ * @protected
+ */
+jspb.Message.setProto3EnumField = function(msg, fieldNumber, value) {
+  jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0);
+};
+
+
+
+/**
+ * Sets the value of a non-extension primitive field, with proto3 (non-nullable
+ * primitives) semantics of ignoring values that are equal to the type's
+ * default.
+ * @template T
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @param {!Uint8Array|string|number|boolean|undefined} value New value
+ * @param {!Uint8Array|string|number|boolean} defaultValue The default value.
+ * @private
+ */
+jspb.Message.setFieldIgnoringDefault_ = function(
+    msg, fieldNumber, value, defaultValue) {
+  if (value != defaultValue) {
+    jspb.Message.setField(msg, fieldNumber, value);
+  } else {
+    msg.array[jspb.Message.getIndex_(msg, fieldNumber)] = null;
+  }
+};
+
+
+/**
  * Adds a value to a repeated, primitive field.
  * @param {!jspb.Message} msg A jspb proto.
  * @param {number} fieldNumber The field number.
diff --git a/js/proto3_test.js b/js/proto3_test.js
index 81d6de2..4aed88b 100644
--- a/js/proto3_test.js
+++ b/js/proto3_test.js
@@ -72,6 +72,37 @@
 
 
 describe('proto3Test', function() {
+
+  /**
+   * Test default values don't affect equality test.
+   */
+  it('testEqualsProto3', function() {
+    var msg1 = new proto.jspb.test.TestProto3();
+    var msg2 = new proto.jspb.test.TestProto3();
+    msg2.setOptionalString('');
+
+    assertTrue(jspb.Message.equals(msg1, msg2));
+  });
+
+
+  /**
+   * Test setting when a field has default semantics.
+   */
+  it('testSetProto3ToValueAndBackToDefault', function() {
+    var msg = new proto.jspb.test.TestProto3();
+
+    // Setting should work normally.
+    msg.setOptionalString('optionalString');
+    assertEquals(msg.getOptionalString(), 'optionalString');
+
+    // Clearing should work too ...
+    msg.setOptionalString('');
+    assertEquals(msg.getOptionalString(), '');
+
+    // ... and shouldn't affect the equality with a brand new message.
+    assertTrue(jspb.Message.equals(msg, new proto.jspb.test.TestProto3()));
+  });
+
   /**
    * Test defaults for proto3 message fields.
    */
@@ -225,52 +256,65 @@
    * Test that oneofs continue to have a notion of field presence.
    */
   it('testOneofs', function() {
+    // Default instance.
     var msg = new proto.jspb.test.TestProto3();
-
     assertEquals(msg.getOneofUint32(), 0);
     assertEquals(msg.getOneofForeignMessage(), undefined);
     assertEquals(msg.getOneofString(), '');
     assertEquals(msg.getOneofBytes(), '');
+
     assertFalse(msg.hasOneofUint32());
+    assertFalse(msg.hasOneofForeignMessage());
     assertFalse(msg.hasOneofString());
     assertFalse(msg.hasOneofBytes());
 
+    // Integer field.
     msg.setOneofUint32(42);
     assertEquals(msg.getOneofUint32(), 42);
     assertEquals(msg.getOneofForeignMessage(), undefined);
     assertEquals(msg.getOneofString(), '');
     assertEquals(msg.getOneofBytes(), '');
+
     assertTrue(msg.hasOneofUint32());
+    assertFalse(msg.hasOneofForeignMessage());
     assertFalse(msg.hasOneofString());
     assertFalse(msg.hasOneofBytes());
 
-
+    // Sub-message field.
     var submsg = new proto.jspb.test.ForeignMessage();
     msg.setOneofForeignMessage(submsg);
     assertEquals(msg.getOneofUint32(), 0);
     assertEquals(msg.getOneofForeignMessage(), submsg);
     assertEquals(msg.getOneofString(), '');
     assertEquals(msg.getOneofBytes(), '');
+
     assertFalse(msg.hasOneofUint32());
+    assertTrue(msg.hasOneofForeignMessage());
     assertFalse(msg.hasOneofString());
     assertFalse(msg.hasOneofBytes());
 
+    // String field.
     msg.setOneofString('hello');
     assertEquals(msg.getOneofUint32(), 0);
     assertEquals(msg.getOneofForeignMessage(), undefined);
     assertEquals(msg.getOneofString(), 'hello');
     assertEquals(msg.getOneofBytes(), '');
+
     assertFalse(msg.hasOneofUint32());
+    assertFalse(msg.hasOneofForeignMessage());
     assertTrue(msg.hasOneofString());
     assertFalse(msg.hasOneofBytes());
 
+    // Bytes field.
     msg.setOneofBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
     assertEquals(msg.getOneofUint32(), 0);
     assertEquals(msg.getOneofForeignMessage(), undefined);
     assertEquals(msg.getOneofString(), '');
     assertEquals(msg.getOneofBytes_asB64(),
         goog.crypt.base64.encodeString('\u00FF\u00FF'));
+
     assertFalse(msg.hasOneofUint32());
+    assertFalse(msg.hasOneofForeignMessage());
     assertFalse(msg.hasOneofString());
     assertTrue(msg.hasOneofBytes());
   });