Integrate google internal changes.
diff --git a/js/proto3_test.js b/js/proto3_test.js
index f886871..4dd7790 100644
--- a/js/proto3_test.js
+++ b/js/proto3_test.js
@@ -28,6 +28,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+goog.require('goog.crypt.base64');
 goog.require('goog.testing.asserts');
 
 // CommonJS-LoadFromFile: testbinary_pb proto.jspb.test
@@ -37,31 +38,30 @@
 goog.require('proto.jspb.test.Proto3Enum');
 goog.require('proto.jspb.test.TestProto3');
 
+
+var BYTES = new Uint8Array([1, 2, 8, 9]);
+var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES);
+
+
 /**
- * Helper: compare a bytes field to a string with codepoints 0--255.
+ * Helper: compare a bytes field to an expected value
  * @param {Uint8Array|string} arr
- * @param {string} str
+ * @param {Uint8Array} expected
  * @return {boolean}
  */
-function bytesCompare(arr, str) {
-  if (arr.length != str.length) {
+function bytesCompare(arr, expected) {
+  if (goog.isString(arr)) {
+    arr = goog.crypt.base64.decodeStringToUint8Array(arr);
+  }
+  if (arr.length != expected.length) {
     return false;
   }
-  if (typeof arr == 'string') {
-    for (var i = 0; i < arr.length; i++) {
-      if (arr.charCodeAt(i) != str.charCodeAt(i)) {
-        return false;
-      }
+  for (var i = 0; i < arr.length; i++) {
+    if (arr[i] != expected[i]) {
+      return false;
     }
-    return true;
-  } else {
-    for (var i = 0; i < arr.length; i++) {
-      if (arr[i] != str.charCodeAt(i)) {
-        return false;
-      }
-    }
-    return true;
   }
+  return true;
 }
 
 
@@ -86,13 +86,17 @@
     assertEquals(msg.getOptionalDouble(), 0);
     assertEquals(msg.getOptionalString(), '');
 
-    // If/when we change bytes fields to return Uint8Array, we'll want to switch
-    // to this assertion instead:
-    //assertEquals(msg.getOptionalBytes() instanceof Uint8Array, true);
+    // TODO(b/26173701): when we change bytes fields default getter to return
+    // Uint8Array, we'll want to switch this assertion to match the u8 case.
     assertEquals(typeof msg.getOptionalBytes(), 'string');
-
+    assertEquals(msg.getOptionalBytes_asU8() instanceof Uint8Array, true);
+    assertEquals(typeof msg.getOptionalBytes_asB64(), 'string');
     assertEquals(msg.getOptionalBytes().length, 0);
-    assertEquals(msg.getOptionalForeignEnum(), proto.jspb.test.Proto3Enum.PROTO3_FOO);
+    assertEquals(msg.getOptionalBytes_asU8().length, 0);
+    assertEquals(msg.getOptionalBytes_asB64(), '');
+
+    assertEquals(msg.getOptionalForeignEnum(),
+                 proto.jspb.test.Proto3Enum.PROTO3_FOO);
     assertEquals(msg.getOptionalForeignMessage(), undefined);
     assertEquals(msg.getOptionalForeignMessage(), undefined);
 
@@ -136,7 +140,7 @@
     msg.setOptionalDouble(-1.5);
     msg.setOptionalBool(true);
     msg.setOptionalString('hello world');
-    msg.setOptionalBytes('bytes');
+    msg.setOptionalBytes(BYTES);
     var submsg = new proto.jspb.test.ForeignMessage();
     submsg.setC(16);
     msg.setOptionalForeignMessage(submsg);
@@ -156,7 +160,7 @@
     msg.setRepeatedDoubleList([-1.5]);
     msg.setRepeatedBoolList([true]);
     msg.setRepeatedStringList(['hello world']);
-    msg.setRepeatedBytesList(['bytes']);
+    msg.setRepeatedBytesList([BYTES]);
     submsg = new proto.jspb.test.ForeignMessage();
     submsg.setC(1000);
     msg.setRepeatedForeignMessageList([submsg]);
@@ -181,7 +185,7 @@
     assertEquals(msg.getOptionalDouble(), -1.5);
     assertEquals(msg.getOptionalBool(), true);
     assertEquals(msg.getOptionalString(), 'hello world');
-    assertEquals(true, bytesCompare(msg.getOptionalBytes(), 'bytes'));
+    assertEquals(true, bytesCompare(msg.getOptionalBytes(), BYTES));
     assertEquals(msg.getOptionalForeignMessage().getC(), 16);
     assertEquals(msg.getOptionalForeignEnum(),
         proto.jspb.test.Proto3Enum.PROTO3_BAR);
@@ -201,7 +205,7 @@
     assertElementsEquals(msg.getRepeatedBoolList(), [true]);
     assertElementsEquals(msg.getRepeatedStringList(), ['hello world']);
     assertEquals(msg.getRepeatedBytesList().length, 1);
-    assertEquals(true, bytesCompare(msg.getRepeatedBytesList()[0], 'bytes'));
+    assertEquals(true, bytesCompare(msg.getRepeatedBytesList()[0], BYTES));
     assertEquals(msg.getRepeatedForeignMessageList().length, 1);
     assertEquals(msg.getRepeatedForeignMessageList()[0].getC(), 1000);
     assertElementsEquals(msg.getRepeatedForeignEnumList(),
@@ -242,11 +246,12 @@
     assertEquals(msg.getOneofString(), 'hello');
     assertEquals(msg.getOneofBytes(), undefined);
 
-    msg.setOneofBytes('\u00FF\u00FF');
+    msg.setOneofBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
     assertEquals(msg.getOneofUint32(), undefined);
     assertEquals(msg.getOneofForeignMessage(), undefined);
     assertEquals(msg.getOneofString(), undefined);
-    assertEquals(msg.getOneofBytes(), '\u00FF\u00FF');
+    assertEquals(msg.getOneofBytes_asB64(),
+        goog.crypt.base64.encodeString('\u00FF\u00FF'));
   });
 
 
@@ -267,7 +272,7 @@
     msg.setOptionalBool(false);
     msg.setOptionalString('hello world');
     msg.setOptionalString('');
-    msg.setOptionalBytes('\u00FF\u00FF');
+    msg.setOptionalBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
     msg.setOptionalBytes('');
     msg.setOptionalForeignMessage(new proto.jspb.test.ForeignMessage());
     msg.setOptionalForeignMessage(null);
@@ -280,4 +285,30 @@
     var serialized = msg.serializeBinary();
     assertEquals(0, serialized.length);
   });
+
+  /**
+   * Test that base64 string and Uint8Array are interchangeable in bytes fields.
+   */
+  it('testBytesFieldsInterop', function() {
+    var msg = new proto.jspb.test.TestProto3();
+    // Set as a base64 string and check all the getters work.
+    msg.setOptionalBytes(BYTES_B64);
+    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+    // Test binary serialize round trip doesn't break it.
+    msg = proto.jspb.test.TestProto3.deserializeBinary(msg.serializeBinary());
+    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+    msg = new proto.jspb.test.TestProto3();
+    // Set as a Uint8Array and check all the getters work.
+    msg.setOptionalBytes(BYTES);
+    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+  });
 });