Merge pull request #7154 from tswast/issue4498-googleapis.dev

python: publish sphinx docs to googleapis.dev
diff --git a/BUILD b/BUILD
index 79871d6..c45fc45 100644
--- a/BUILD
+++ b/BUILD
@@ -1,7 +1,6 @@
 # Bazel (https://bazel.build/) BUILD file for Protobuf.
 
 load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test", "objc_library", native_cc_proto_library = "cc_proto_library")
-load("@rules_java//java:defs.bzl", "java_library")
 load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain", "proto_library")
 load("@rules_proto//proto/private:native.bzl", "native_proto_common")
 load("@rules_python//python:defs.bzl", "py_library")
@@ -12,17 +11,6 @@
 exports_files(["LICENSE"])
 
 ################################################################################
-# Java 9 configuration
-################################################################################
-
-config_setting(
-    name = "jdk9",
-    values = {
-        "java_toolchain": "@bazel_tools//tools/jdk:toolchain_jdk9",
-    },
-)
-
-################################################################################
 # ZLIB configuration
 ################################################################################
 
@@ -70,6 +58,10 @@
 create_compiler_config_setting(
     name = "msvc",
     value = "msvc-cl",
+    visibility = [
+        # Public, but Protobuf only visibility.
+        "//:__subpackages__",
+    ],
 )
 
 config_setting(
@@ -77,6 +69,10 @@
     values = {
         "crosstool_top": "//external:android/crosstool",
     },
+    visibility = [
+        # Public, but Protobuf only visibility.
+        "//:__subpackages__",
+    ],
 )
 
 config_setting(
@@ -84,6 +80,10 @@
     values = {
         "crosstool_top": "@androidndk//:toolchain-libcpp",
     },
+    visibility = [
+        # Public, but Protobuf only visibility.
+        "//:__subpackages__",
+    ],
 )
 
 config_setting(
@@ -91,6 +91,10 @@
     values = {
         "crosstool_top": "@androidndk//:toolchain-gnu-libstdcpp",
     },
+    visibility = [
+        # Public, but Protobuf only visibility.
+        "//:__subpackages__",
+    ],
 )
 
 # Android and MSVC builds do not need to link in a separate pthread library.
@@ -653,144 +657,43 @@
 ################################################################################
 # Java support
 ################################################################################
+
 internal_gen_well_known_protos_java(
-    srcs = WELL_KNOWN_PROTOS,
+    name = "gen_well_known_protos_java",
+    deps = [proto + "_proto" for proto in WELL_KNOWN_PROTO_MAP.keys()],
+    visibility = [
+        "//java:__subpackages__",
+    ],
 )
 
-java_library(
+alias(
     name = "protobuf_java",
-    srcs = glob([
-        "java/core/src/main/java/com/google/protobuf/*.java",
-    ]) + [
-        ":gen_well_known_protos_java",
-    ],
-    javacopts = select({
-        "//:jdk9": ["--add-modules=jdk.unsupported"],
-        "//conditions:default": [
-            "-source 7",
-            "-target 7",
-        ],
-    }),
+    actual = "//java/core",
     visibility = ["//visibility:public"],
 )
 
-java_library(
+alias(
     name = "protobuf_javalite",
-    srcs = [
-        # Keep in sync with java/lite/pom.xml
-        "java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java",
-        "java/core/src/main/java/com/google/protobuf/AbstractParser.java",
-        "java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java",
-        "java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java",
-        "java/core/src/main/java/com/google/protobuf/Android.java",
-        "java/core/src/main/java/com/google/protobuf/ArrayDecoders.java",
-        "java/core/src/main/java/com/google/protobuf/BinaryReader.java",
-        "java/core/src/main/java/com/google/protobuf/BinaryWriter.java",
-        "java/core/src/main/java/com/google/protobuf/BooleanArrayList.java",
-        "java/core/src/main/java/com/google/protobuf/BufferAllocator.java",
-        "java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java",
-        "java/core/src/main/java/com/google/protobuf/ByteOutput.java",
-        "java/core/src/main/java/com/google/protobuf/ByteString.java",
-        "java/core/src/main/java/com/google/protobuf/CodedInputStream.java",
-        "java/core/src/main/java/com/google/protobuf/CodedInputStreamReader.java",
-        "java/core/src/main/java/com/google/protobuf/CodedOutputStream.java",
-        "java/core/src/main/java/com/google/protobuf/CodedOutputStreamWriter.java",
-        "java/core/src/main/java/com/google/protobuf/DoubleArrayList.java",
-        "java/core/src/main/java/com/google/protobuf/ExperimentalApi.java",
-        "java/core/src/main/java/com/google/protobuf/ExtensionLite.java",
-        "java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java",
-        "java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java",
-        "java/core/src/main/java/com/google/protobuf/ExtensionSchema.java",
-        "java/core/src/main/java/com/google/protobuf/ExtensionSchemaLite.java",
-        "java/core/src/main/java/com/google/protobuf/ExtensionSchemas.java",
-        "java/core/src/main/java/com/google/protobuf/FieldInfo.java",
-        "java/core/src/main/java/com/google/protobuf/FieldSet.java",
-        "java/core/src/main/java/com/google/protobuf/FieldType.java",
-        "java/core/src/main/java/com/google/protobuf/FloatArrayList.java",
-        "java/core/src/main/java/com/google/protobuf/GeneratedMessageInfoFactory.java",
-        "java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java",
-        "java/core/src/main/java/com/google/protobuf/IntArrayList.java",
-        "java/core/src/main/java/com/google/protobuf/Internal.java",
-        "java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java",
-        "java/core/src/main/java/com/google/protobuf/IterableByteBufferInputStream.java",
-        "java/core/src/main/java/com/google/protobuf/JavaType.java",
-        "java/core/src/main/java/com/google/protobuf/LazyField.java",
-        "java/core/src/main/java/com/google/protobuf/LazyFieldLite.java",
-        "java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java",
-        "java/core/src/main/java/com/google/protobuf/LazyStringList.java",
-        "java/core/src/main/java/com/google/protobuf/ListFieldSchema.java",
-        "java/core/src/main/java/com/google/protobuf/LongArrayList.java",
-        "java/core/src/main/java/com/google/protobuf/ManifestSchemaFactory.java",
-        "java/core/src/main/java/com/google/protobuf/MapEntryLite.java",
-        "java/core/src/main/java/com/google/protobuf/MapFieldLite.java",
-        "java/core/src/main/java/com/google/protobuf/MapFieldSchema.java",
-        "java/core/src/main/java/com/google/protobuf/MapFieldSchemaLite.java",
-        "java/core/src/main/java/com/google/protobuf/MapFieldSchemas.java",
-        "java/core/src/main/java/com/google/protobuf/MessageInfo.java",
-        "java/core/src/main/java/com/google/protobuf/MessageInfoFactory.java",
-        "java/core/src/main/java/com/google/protobuf/MessageLite.java",
-        "java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java",
-        "java/core/src/main/java/com/google/protobuf/MessageLiteToString.java",
-        "java/core/src/main/java/com/google/protobuf/MessageSchema.java",
-        "java/core/src/main/java/com/google/protobuf/MessageSetSchema.java",
-        "java/core/src/main/java/com/google/protobuf/MutabilityOracle.java",
-        "java/core/src/main/java/com/google/protobuf/NewInstanceSchema.java",
-        "java/core/src/main/java/com/google/protobuf/NewInstanceSchemaLite.java",
-        "java/core/src/main/java/com/google/protobuf/NewInstanceSchemas.java",
-        "java/core/src/main/java/com/google/protobuf/NioByteString.java",
-        "java/core/src/main/java/com/google/protobuf/OneofInfo.java",
-        "java/core/src/main/java/com/google/protobuf/Parser.java",
-        "java/core/src/main/java/com/google/protobuf/PrimitiveNonBoxingCollection.java",
-        "java/core/src/main/java/com/google/protobuf/ProtoSyntax.java",
-        "java/core/src/main/java/com/google/protobuf/Protobuf.java",
-        "java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java",
-        "java/core/src/main/java/com/google/protobuf/ProtobufLists.java",
-        "java/core/src/main/java/com/google/protobuf/ProtocolStringList.java",
-        "java/core/src/main/java/com/google/protobuf/RawMessageInfo.java",
-        "java/core/src/main/java/com/google/protobuf/Reader.java",
-        "java/core/src/main/java/com/google/protobuf/RopeByteString.java",
-        "java/core/src/main/java/com/google/protobuf/Schema.java",
-        "java/core/src/main/java/com/google/protobuf/SchemaFactory.java",
-        "java/core/src/main/java/com/google/protobuf/SchemaUtil.java",
-        "java/core/src/main/java/com/google/protobuf/SmallSortedMap.java",
-        "java/core/src/main/java/com/google/protobuf/StructuralMessageInfo.java",
-        "java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java",
-        "java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java",
-        "java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java",
-        "java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java",
-        "java/core/src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java",
-        "java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java",
-        "java/core/src/main/java/com/google/protobuf/UnsafeUtil.java",
-        "java/core/src/main/java/com/google/protobuf/Utf8.java",
-        "java/core/src/main/java/com/google/protobuf/WireFormat.java",
-        "java/core/src/main/java/com/google/protobuf/Writer.java",
-    ],
-    javacopts = select({
-        "//:jdk9": ["--add-modules=jdk.unsupported"],
-        "//conditions:default": [
-            "-source 7",
-            "-target 7",
-        ],
-    }),
+    actual = "//java/lite",
     visibility = ["//visibility:public"],
 )
 
-java_library(
+alias(
     name = "protobuf_java_util",
-    srcs = glob([
-        "java/util/src/main/java/com/google/protobuf/util/*.java",
-    ]),
-    javacopts = [
-        "-source 7",
-        "-target 7",
-    ],
+    actual = "//java/util",
     visibility = ["//visibility:public"],
-    deps = [
-        "protobuf_java",
-        "//external:error_prone_annotations",
-        "//external:gson",
-        "//external:guava",
-    ],
+)
+
+alias(
+    name = "java_toolchain",
+    actual = "//java/core:toolchain",
+    visibility = ["//visibility:public"],
+)
+
+alias(
+    name = "javalite_toolchain",
+    actual = "//java/lite:toolchain",
+    visibility = ["//visibility:public"],
 )
 
 ################################################################################
@@ -859,6 +762,10 @@
     values = {
         "define": "use_fast_cpp_protos=true",
     },
+    visibility = [
+        # Public, but Protobuf only visibility.
+        "//:__subpackages__",
+    ],
 )
 
 config_setting(
@@ -866,6 +773,10 @@
     values = {
         "define": "allow_oversize_protos=true",
     },
+    visibility = [
+        # Public, but Protobuf only visibility.
+        "//:__subpackages__",
+    ],
 )
 
 # Copy the builtin proto files from src/google/protobuf to
@@ -1011,20 +922,6 @@
     visibility = ["//visibility:public"],
 )
 
-proto_lang_toolchain(
-    name = "java_toolchain",
-    command_line = "--java_out=$(OUT)",
-    runtime = ":protobuf_java",
-    visibility = ["//visibility:public"],
-)
-
-proto_lang_toolchain(
-    name = "javalite_toolchain",
-    command_line = "--java_out=lite:$(OUT)",
-    runtime = ":protobuf_javalite",
-    visibility = ["//visibility:public"],
-)
-
 alias(
     name = "objectivec",
     actual = ":protobuf_objc",
diff --git a/CHANGES.txt b/CHANGES.txt
index 48bd7af..cbd3a20 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,23 @@
+2020-02-14 version 3.11.4 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+  
+  C#
+  * Fix latest ArgumentException for C# extensions (#7188)
+  * Enforce recursion depth checking for unknown fields (#7210)
+  
+  Ruby
+  * Fix wrappers with a zero value (#7195)
+  * Fix JSON serialization of 0/empty-valued wrapper types (#7198)
+
+2020-01-31 version 3.11.3 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  C++
+  * Add OUT and OPTIONAL to windows portability files (#7087)
+
+  PHP
+  * Refactored ulong to zend_ulong for php7.4 compatibility (#7147)
+  * Call register_class before getClass from desc to fix segfault (#7077)
+  
+
 2019-12-10 version 3.11.2 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
 
   PHP
diff --git a/Makefile.am b/Makefile.am
index 704aad6..b4e6ebd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -247,8 +247,10 @@
   csharp/src/Google.Protobuf/UnknownFieldSet.cs
 
 java_EXTRA_DIST=                                                                   \
+  java/BUILD                                                                       \
   java/README.md                                                                   \
   java/bom/pom.xml                                                                 \
+  java/core/BUILD                                                                  \
   java/core/generate-sources-build.xml                                             \
   java/core/generate-test-sources-build.xml                                        \
   java/core/pom.xml                                                                \
@@ -504,6 +506,7 @@
   java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto         \
   java/core/src/test/proto/com/google/protobuf/wrappers_test.proto                 \
   java/lite.md                                                                     \
+  java/lite/BUILD                                                                  \
   java/lite/generate-sources-build.xml                                             \
   java/lite/generate-test-sources-build.xml                                        \
   java/lite/lite.awk                                                               \
@@ -512,6 +515,7 @@
   java/lite/src/test/java/com/google/protobuf/LiteTest.java                        \
   java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java    \
   java/pom.xml                                                                     \
+  java/util/BUILD                                                                  \
   java/util/pom.xml                                                                \
   java/util/src/main/java/com/google/protobuf/util/Durations.java                  \
   java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java              \
@@ -1213,6 +1217,7 @@
   js/test_bootstrap.js                                                 \
   js/testbinary.proto                                                  \
   js/testempty.proto                                                   \
+  js/testlargenumbers.proto                                            \
   js/experimental/runtime/testing/jasmine_protobuf.js                  \
   js/experimental/runtime/testing/ensure_custom_equality_test.js       \
   js/experimental/runtime/testing/binary/test_message.js               \
@@ -1298,7 +1303,7 @@
   WORKSPACE                              \
   cmake/CMakeLists.txt                   \
   cmake/README.md                        \
-  cmake/conformance.cmake                   \
+  cmake/conformance.cmake                \
   cmake/examples.cmake                   \
   cmake/extract_includes.bat.in          \
   cmake/install.cmake                    \
@@ -1315,6 +1320,8 @@
   cmake/tests.cmake                      \
   cmake/version.rc.in                    \
   compiler_config_setting.bzl            \
+  build_files_updated_unittest.sh        \
+  cc_proto_blacklist_test.bzl            \
   editors/README.txt                     \
   editors/proto.vim                      \
   editors/protobuf-mode.el               \
diff --git a/Protobuf-C++.podspec b/Protobuf-C++.podspec
index 1359d02..dcb9f4d 100644
--- a/Protobuf-C++.podspec
+++ b/Protobuf-C++.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name     = 'Protobuf-C++'
-  s.version  = '3.11.2'
+  s.version  = '3.11.4'
   s.summary  = 'Protocol Buffers v3 runtime library for C++.'
   s.homepage = 'https://github.com/google/protobuf'
   s.license  = '3-Clause BSD License'
diff --git a/Protobuf.podspec b/Protobuf.podspec
index 0371b7b..d6d6a8e 100644
--- a/Protobuf.podspec
+++ b/Protobuf.podspec
@@ -5,7 +5,7 @@
 # dependent projects use the :git notation to refer to the library.
 Pod::Spec.new do |s|
   s.name     = 'Protobuf'
-  s.version  = '3.11.2'
+  s.version  = '3.11.4'
   s.summary  = 'Protocol Buffers v.3 runtime library for Objective-C.'
   s.homepage = 'https://github.com/protocolbuffers/protobuf'
   s.license  = '3-Clause BSD License'
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index 8e5e680..8496799 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -28,6 +28,14 @@
   set(CMAKE_CXX_EXTENSIONS OFF)
 endif()
 
+# The Intel compiler isn't able to deal with noinline member functions of
+# template classses defined in headers.  As such it spams the output with
+#   warning #2196: routine is both "inline" and "noinline"
+# This silences that warning.
+if (CMAKE_CXX_COMPILER_ID MATCHES Intel)
+  string(APPEND CMAKE_CXX_FLAGS " -diag-disable=2196")
+endif()
+
 # Options
 option(protobuf_BUILD_TESTS "Build tests" ON)
 option(protobuf_BUILD_CONFORMANCE "Build conformance tests" OFF)
diff --git a/compiler_config_setting.bzl b/compiler_config_setting.bzl
index 5e52a65..f4d1f7b 100644
--- a/compiler_config_setting.bzl
+++ b/compiler_config_setting.bzl
@@ -1,6 +1,6 @@
 """Creates config_setting that allows selecting based on 'compiler' value."""
 
-def create_compiler_config_setting(name, value):
+def create_compiler_config_setting(name, value, visibility = None):
     # The "do_not_use_tools_cpp_compiler_present" attribute exists to
     # distinguish between older versions of Bazel that do not support
     # "@bazel_tools//tools/cpp:compiler" flag_value, and newer ones that do.
@@ -13,9 +13,11 @@
             flag_values = {
                 "@bazel_tools//tools/cpp:compiler": value,
             },
+            visibility = visibility,
         )
     else:
         native.config_setting(
             name = name,
             values = {"compiler": value},
+            visibility = visibility,
         )
diff --git a/configure.ac b/configure.ac
index df39c05..a86499a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,7 +17,7 @@
 # In the SVN trunk, the version should always be the next anticipated release
 # version with the "-pre" suffix.  (We used to use "-SNAPSHOT" but this pushed
 # the size of one file name in the dist tarfile over the 99-char limit.)
-AC_INIT([Protocol Buffers],[3.11.2],[protobuf@googlegroups.com],[protobuf])
+AC_INIT([Protocol Buffers],[3.11.4],[protobuf@googlegroups.com],[protobuf])
 
 AM_MAINTAINER_MODE([enable])
 
diff --git a/conformance/failure_list_ruby.txt b/conformance/failure_list_ruby.txt
index 4573c59..f9533ae 100644
--- a/conformance/failure_list_ruby.txt
+++ b/conformance/failure_list_ruby.txt
@@ -94,25 +94,7 @@
 Required.Proto3.JsonInput.IgnoreUnknownJsonString.ProtobufOutput
 Required.Proto3.JsonInput.IgnoreUnknownJsonTrue.ProtobufOutput
 Required.Proto3.JsonInput.OneofFieldDuplicate
-Required.Proto3.JsonInput.OptionalBoolWrapper.JsonOutput
-Required.Proto3.JsonInput.OptionalBytesWrapper.JsonOutput
-Required.Proto3.JsonInput.OptionalDoubleWrapper.JsonOutput
-Required.Proto3.JsonInput.OptionalFloatWrapper.JsonOutput
-Required.Proto3.JsonInput.OptionalInt32Wrapper.JsonOutput
-Required.Proto3.JsonInput.OptionalInt64Wrapper.JsonOutput
-Required.Proto3.JsonInput.OptionalStringWrapper.JsonOutput
-Required.Proto3.JsonInput.OptionalUint32Wrapper.JsonOutput
-Required.Proto3.JsonInput.OptionalUint64Wrapper.JsonOutput
 Required.Proto3.JsonInput.RejectTopLevelNull
-Required.Proto3.JsonInput.RepeatedBoolWrapper.JsonOutput
-Required.Proto3.JsonInput.RepeatedBytesWrapper.JsonOutput
-Required.Proto3.JsonInput.RepeatedDoubleWrapper.JsonOutput
-Required.Proto3.JsonInput.RepeatedFloatWrapper.JsonOutput
-Required.Proto3.JsonInput.RepeatedInt32Wrapper.JsonOutput
-Required.Proto3.JsonInput.RepeatedInt64Wrapper.JsonOutput
-Required.Proto3.JsonInput.RepeatedStringWrapper.JsonOutput
-Required.Proto3.JsonInput.RepeatedUint32Wrapper.JsonOutput
-Required.Proto3.JsonInput.RepeatedUint64Wrapper.JsonOutput
 Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput
 Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput
 Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
diff --git a/csharp/Google.Protobuf.Tools.nuspec b/csharp/Google.Protobuf.Tools.nuspec
index 3823e20..91d28ed 100644
--- a/csharp/Google.Protobuf.Tools.nuspec
+++ b/csharp/Google.Protobuf.Tools.nuspec
@@ -5,7 +5,7 @@
     <title>Google Protocol Buffers tools</title>
     <summary>Tools for Protocol Buffers - Google's data interchange format.</summary>
     <description>See project site for more info.</description>
-    <version>3.11.2</version>
+    <version>3.11.4</version>
     <authors>Google Inc.</authors>
     <owners>protobuf-packages</owners>
     <licenseUrl>https://github.com/protocolbuffers/protobuf/blob/master/LICENSE</licenseUrl>
@@ -20,7 +20,6 @@
     <file src="protoc\windows_x64\protoc.exe" target="tools\windows_x64\protoc.exe"/>
     <file src="protoc\linux_x86\protoc" target="tools\linux_x86\protoc"/>
     <file src="protoc\linux_x64\protoc" target="tools\linux_x64\protoc"/>
-    <file src="protoc\macosx_x86\protoc" target="tools\macosx_x86\protoc"/>
     <file src="protoc\macosx_x64\protoc" target="tools\macosx_x64\protoc"/>
     <file src="..\src\google\protobuf\any.proto" target="tools\google\protobuf"/>
     <file src="..\src\google\protobuf\api.proto" target="tools\google\protobuf"/>
diff --git a/csharp/build_tools.sh b/csharp/build_tools.sh
index 182c5c5..771affd 100755
--- a/csharp/build_tools.sh
+++ b/csharp/build_tools.sh
@@ -19,7 +19,6 @@
 declare -a FILE_NAMES=(          \
   windows_x86 windows-x86_32.exe \
   windows_x64 windows-x86_64.exe \
-  macosx_x86  osx-x86_32.exe     \
   macosx_x64  osx-x86_64.exe     \
   linux_x86   linux-x86_32.exe   \
   linux_x64   linux-x86_64.exe   \
diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
index e8e33e2..53f45fe 100644
--- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj
+++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
@@ -4,7 +4,7 @@
     <Description>C# runtime library for Protocol Buffers - Google's data interchange format.</Description>
     <Copyright>Copyright 2015, Google Inc.</Copyright>
     <AssemblyTitle>Google Protocol Buffers</AssemblyTitle>
-    <VersionPrefix>3.11.2</VersionPrefix>
+    <VersionPrefix>3.11.4</VersionPrefix>
     <LangVersion>6</LangVersion>
     <Authors>Google Inc.</Authors>
     <TargetFrameworks>netstandard1.0;netstandard2.0;net45</TargetFrameworks>
diff --git a/docs/options.md b/docs/options.md
index ad7cd0d..5e90579 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -224,3 +224,7 @@
 1. Wire since and until
    * Website: https://square.github.io/wire/
    * Extensions: 1076, 1077
+
+1. Bazel, Failure Details
+   * Website: https://github.com/bazelbuild/bazel
+   * Extensions: 1078
diff --git a/examples/.gitignore b/examples/.gitignore
new file mode 100644
index 0000000..229542d
--- /dev/null
+++ b/examples/.gitignore
@@ -0,0 +1,2 @@
+# Ignore the bazel symlinks
+/bazel-*
diff --git a/java/BUILD b/java/BUILD
new file mode 100644
index 0000000..779fa9e
--- /dev/null
+++ b/java/BUILD
@@ -0,0 +1,9 @@
+config_setting(
+    name = "jdk9",
+    values = {
+        "java_toolchain": "@bazel_tools//tools/jdk:toolchain_jdk9",
+    },
+    visibility = [
+        "//java:__subpackages__",
+    ],
+)
diff --git a/java/bom/pom.xml b/java/bom/pom.xml
index ea15d48..f499bd1 100644
--- a/java/bom/pom.xml
+++ b/java/bom/pom.xml
@@ -4,7 +4,7 @@
 
   <groupId>com.google.protobuf</groupId>
   <artifactId>protobuf-bom</artifactId>
-  <version>3.11.2</version>
+  <version>3.11.4</version>
   <packaging>pom</packaging>
 
   <name>Protocol Buffers [BOM]</name>
diff --git a/java/core/BUILD b/java/core/BUILD
new file mode 100644
index 0000000..5f4a7ab
--- /dev/null
+++ b/java/core/BUILD
@@ -0,0 +1,137 @@
+load("@rules_java//java:defs.bzl", "java_library")
+load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain")
+
+LITE_SRCS = [
+    # Keep in sync with `//java/lite:pom.xml`.
+    "src/main/java/com/google/protobuf/AbstractMessageLite.java",
+    "src/main/java/com/google/protobuf/AbstractParser.java",
+    "src/main/java/com/google/protobuf/AbstractProtobufList.java",
+    "src/main/java/com/google/protobuf/AllocatedBuffer.java",
+    "src/main/java/com/google/protobuf/Android.java",
+    "src/main/java/com/google/protobuf/ArrayDecoders.java",
+    "src/main/java/com/google/protobuf/BinaryReader.java",
+    "src/main/java/com/google/protobuf/BinaryWriter.java",
+    "src/main/java/com/google/protobuf/BooleanArrayList.java",
+    "src/main/java/com/google/protobuf/BufferAllocator.java",
+    "src/main/java/com/google/protobuf/ByteBufferWriter.java",
+    "src/main/java/com/google/protobuf/ByteOutput.java",
+    "src/main/java/com/google/protobuf/ByteString.java",
+    "src/main/java/com/google/protobuf/CodedInputStream.java",
+    "src/main/java/com/google/protobuf/CodedInputStreamReader.java",
+    "src/main/java/com/google/protobuf/CodedOutputStream.java",
+    "src/main/java/com/google/protobuf/CodedOutputStreamWriter.java",
+    "src/main/java/com/google/protobuf/DoubleArrayList.java",
+    "src/main/java/com/google/protobuf/ExperimentalApi.java",
+    "src/main/java/com/google/protobuf/ExtensionLite.java",
+    "src/main/java/com/google/protobuf/ExtensionRegistryFactory.java",
+    "src/main/java/com/google/protobuf/ExtensionRegistryLite.java",
+    "src/main/java/com/google/protobuf/ExtensionSchema.java",
+    "src/main/java/com/google/protobuf/ExtensionSchemaLite.java",
+    "src/main/java/com/google/protobuf/ExtensionSchemas.java",
+    "src/main/java/com/google/protobuf/FieldInfo.java",
+    "src/main/java/com/google/protobuf/FieldSet.java",
+    "src/main/java/com/google/protobuf/FieldType.java",
+    "src/main/java/com/google/protobuf/FloatArrayList.java",
+    "src/main/java/com/google/protobuf/GeneratedMessageInfoFactory.java",
+    "src/main/java/com/google/protobuf/GeneratedMessageLite.java",
+    "src/main/java/com/google/protobuf/IntArrayList.java",
+    "src/main/java/com/google/protobuf/Internal.java",
+    "src/main/java/com/google/protobuf/InvalidProtocolBufferException.java",
+    "src/main/java/com/google/protobuf/IterableByteBufferInputStream.java",
+    "src/main/java/com/google/protobuf/JavaType.java",
+    "src/main/java/com/google/protobuf/LazyField.java",
+    "src/main/java/com/google/protobuf/LazyFieldLite.java",
+    "src/main/java/com/google/protobuf/LazyStringArrayList.java",
+    "src/main/java/com/google/protobuf/LazyStringList.java",
+    "src/main/java/com/google/protobuf/ListFieldSchema.java",
+    "src/main/java/com/google/protobuf/LongArrayList.java",
+    "src/main/java/com/google/protobuf/ManifestSchemaFactory.java",
+    "src/main/java/com/google/protobuf/MapEntryLite.java",
+    "src/main/java/com/google/protobuf/MapFieldLite.java",
+    "src/main/java/com/google/protobuf/MapFieldSchema.java",
+    "src/main/java/com/google/protobuf/MapFieldSchemaLite.java",
+    "src/main/java/com/google/protobuf/MapFieldSchemas.java",
+    "src/main/java/com/google/protobuf/MessageInfo.java",
+    "src/main/java/com/google/protobuf/MessageInfoFactory.java",
+    "src/main/java/com/google/protobuf/MessageLite.java",
+    "src/main/java/com/google/protobuf/MessageLiteOrBuilder.java",
+    "src/main/java/com/google/protobuf/MessageLiteToString.java",
+    "src/main/java/com/google/protobuf/MessageSchema.java",
+    "src/main/java/com/google/protobuf/MessageSetSchema.java",
+    "src/main/java/com/google/protobuf/MutabilityOracle.java",
+    "src/main/java/com/google/protobuf/NewInstanceSchema.java",
+    "src/main/java/com/google/protobuf/NewInstanceSchemaLite.java",
+    "src/main/java/com/google/protobuf/NewInstanceSchemas.java",
+    "src/main/java/com/google/protobuf/NioByteString.java",
+    "src/main/java/com/google/protobuf/OneofInfo.java",
+    "src/main/java/com/google/protobuf/Parser.java",
+    "src/main/java/com/google/protobuf/PrimitiveNonBoxingCollection.java",
+    "src/main/java/com/google/protobuf/ProtoSyntax.java",
+    "src/main/java/com/google/protobuf/Protobuf.java",
+    "src/main/java/com/google/protobuf/ProtobufArrayList.java",
+    "src/main/java/com/google/protobuf/ProtobufLists.java",
+    "src/main/java/com/google/protobuf/ProtocolStringList.java",
+    "src/main/java/com/google/protobuf/RawMessageInfo.java",
+    "src/main/java/com/google/protobuf/Reader.java",
+    "src/main/java/com/google/protobuf/RopeByteString.java",
+    "src/main/java/com/google/protobuf/Schema.java",
+    "src/main/java/com/google/protobuf/SchemaFactory.java",
+    "src/main/java/com/google/protobuf/SchemaUtil.java",
+    "src/main/java/com/google/protobuf/SmallSortedMap.java",
+    "src/main/java/com/google/protobuf/StructuralMessageInfo.java",
+    "src/main/java/com/google/protobuf/TextFormatEscaper.java",
+    "src/main/java/com/google/protobuf/UninitializedMessageException.java",
+    "src/main/java/com/google/protobuf/UnknownFieldSchema.java",
+    "src/main/java/com/google/protobuf/UnknownFieldSetLite.java",
+    "src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java",
+    "src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java",
+    "src/main/java/com/google/protobuf/UnsafeUtil.java",
+    "src/main/java/com/google/protobuf/Utf8.java",
+    "src/main/java/com/google/protobuf/WireFormat.java",
+    "src/main/java/com/google/protobuf/Writer.java",
+]
+
+javacopts = select({
+    "//java:jdk9": ["--add-modules=jdk.unsupported"],
+    "//conditions:default": [
+        "-source 7",
+        "-target 7",
+    ],
+})
+
+# Should be used as `//java/lite`.
+java_library(
+    name = "lite",
+    srcs = LITE_SRCS,
+    javacopts = javacopts,
+    visibility = [
+        "//java/lite:__pkg__",
+    ],
+)
+
+java_library(
+    name = "core",
+    srcs = glob(
+        [
+            "src/main/java/com/google/protobuf/*.java",
+        ],
+        exclude = LITE_SRCS,
+    ) + [
+        "//:gen_well_known_protos_java",
+    ],
+    javacopts = javacopts,
+    visibility = ["//visibility:public"],
+    exports = [
+        "//java/lite",
+    ],
+    deps = [
+        "//java/lite",
+    ],
+)
+
+proto_lang_toolchain(
+    name = "toolchain",
+    command_line = "--java_out=$(OUT)",
+    runtime = ":core",
+    visibility = ["//visibility:public"],
+)
diff --git a/java/core/pom.xml b/java/core/pom.xml
index a57f2aa..79a1e71 100644
--- a/java/core/pom.xml
+++ b/java/core/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>com.google.protobuf</groupId>
     <artifactId>protobuf-parent</artifactId>
-    <version>3.11.2</version>
+    <version>3.11.4</version>
   </parent>
 
   <artifactId>protobuf-java</artifactId>
diff --git a/java/lite/BUILD b/java/lite/BUILD
new file mode 100644
index 0000000..22840ec
--- /dev/null
+++ b/java/lite/BUILD
@@ -0,0 +1,14 @@
+load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain")
+
+alias(
+    name = "lite",
+    actual = "//java/core:lite",
+    visibility = ["//visibility:public"],
+)
+
+proto_lang_toolchain(
+    name = "toolchain",
+    command_line = "--java_out=lite:$(OUT)",
+    runtime = ":lite",
+    visibility = ["//visibility:public"],
+)
diff --git a/java/lite/pom.xml b/java/lite/pom.xml
index 81e0521..9c7d6ef 100644
--- a/java/lite/pom.xml
+++ b/java/lite/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>com.google.protobuf</groupId>
     <artifactId>protobuf-parent</artifactId>
-    <version>3.11.2</version>
+    <version>3.11.4</version>
   </parent>
 
   <artifactId>protobuf-javalite</artifactId>
@@ -89,7 +89,7 @@
                 <resource>
                   <directory>${basedir}/../core/src/main/java/com/google/protobuf</directory>
                   <includes>
-                    <!-- Keep in sync with //:BUILD  -->
+                    <!-- Keep in sync with //java/core:BUILD  -->
                     <include>AbstractMessageLite.java</include>
                     <include>AbstractParser.java</include>
                     <include>AbstractProtobufList.java</include>
diff --git a/java/pom.xml b/java/pom.xml
index 8d07e08..2889f90 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -4,7 +4,7 @@
 
   <groupId>com.google.protobuf</groupId>
   <artifactId>protobuf-parent</artifactId>
-  <version>3.11.2</version>
+  <version>3.11.4</version>
   <packaging>pom</packaging>
 
   <name>Protocol Buffers [Parent]</name>
diff --git a/java/util/BUILD b/java/util/BUILD
new file mode 100644
index 0000000..cfdb28e
--- /dev/null
+++ b/java/util/BUILD
@@ -0,0 +1,20 @@
+load("@rules_java//java:defs.bzl", "java_library")
+
+java_library(
+    name = "util",
+    srcs = glob([
+        "src/main/java/com/google/protobuf/util/*.java",
+    ]),
+    javacopts = [
+        "-source 7",
+        "-target 7",
+    ],
+    visibility = ["//visibility:public"],
+    deps = [
+        "//external:error_prone_annotations",
+        "//external:gson",
+        "//external:guava",
+        "//java/core",
+        "//java/lite",
+    ],
+)
diff --git a/java/util/pom.xml b/java/util/pom.xml
index 56d6488..58d05d2 100644
--- a/java/util/pom.xml
+++ b/java/util/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>com.google.protobuf</groupId>
     <artifactId>protobuf-parent</artifactId>
-    <version>3.11.2</version>
+    <version>3.11.4</version>
   </parent>
 
   <artifactId>protobuf-java-util</artifactId>
diff --git a/js/experimental/runtime/kernel/buffer_decoder.js b/js/experimental/runtime/kernel/buffer_decoder.js
index 614659a..2b4157e 100644
--- a/js/experimental/runtime/kernel/buffer_decoder.js
+++ b/js/experimental/runtime/kernel/buffer_decoder.js
@@ -6,7 +6,7 @@
 
 const ByteString = goog.require('protobuf.ByteString');
 const functions = goog.require('goog.functions');
-const {POLYFILL_TEXT_ENCODING, checkCriticalElementIndex, checkCriticalPositionIndex, checkState} = goog.require('protobuf.internal.checks');
+const {POLYFILL_TEXT_ENCODING, checkCriticalPositionIndex, checkCriticalState, checkState} = goog.require('protobuf.internal.checks');
 const {byteStringFromUint8ArrayUnsafe} = goog.require('protobuf.byteStringInternal');
 const {concatenateByteArrays} = goog.require('protobuf.binary.uint8arrays');
 const {decode} = goog.require('protobuf.binary.textencoding');
@@ -72,7 +72,9 @@
     /** @private @const {number} */
     this.startIndex_ = startIndex;
     /** @private @const {number} */
-    this.endIndex_ = this.startIndex_ + length;
+    this.endIndex_ = startIndex + length;
+    /** @private {number} */
+    this.cursor_ = startIndex;
   }
 
   /**
@@ -100,11 +102,37 @@
   }
 
   /**
+   * Returns the start position of the next data, i.e. end position of the last
+   * read data + 1.
+   * @return {number}
+   */
+  cursor() {
+    return this.cursor_;
+  }
+
+  /**
+   * Sets the cursor to the specified position.
+   * @param {number} position
+   */
+  setCursor(position) {
+    this.cursor_ = position;
+  }
+
+  /**
+   * Returns if there is more data to read after the current cursor position.
+   * @return {boolean}
+   */
+  hasNext() {
+    return this.cursor_ < this.endIndex_;
+  }
+
+  /**
    * Returns a float32 from a given index
    * @param {number} index
    * @return {number}
    */
   getFloat32(index) {
+    this.cursor_ = index + 4;
     return this.dataView_.getFloat32(index, true);
   }
 
@@ -114,6 +142,7 @@
    * @return {number}
    */
   getFloat64(index) {
+    this.cursor_ = index + 8;
     return this.dataView_.getFloat64(index, true);
   }
 
@@ -123,45 +152,40 @@
    * @return {number}
    */
   getInt32(index) {
+    this.cursor_ = index + 4;
     return this.dataView_.getInt32(index, true);
   }
 
   /**
-   * @param {number} index
-   * @return {number}
-   */
-  getUint8(index) {
-    return this.dataView_.getUint8(index);
-  }
-
-  /**
    * Returns a uint32 from a given index
    * @param {number} index
    * @return {number}
    */
   getUint32(index) {
+    this.cursor_ = index + 4;
     return this.dataView_.getUint32(index, true);
   }
 
   /**
-   * Returns two JS numbers each representing 32 bits of a 64 bit number.
+   * Returns two JS numbers each representing 32 bits of a 64 bit number. Also
+   * sets the cursor to the start of the next block of data.
    * @param {number} index
-   * @return {{lowBits: number, highBits: number, dataStart: number}}
+   * @return {{lowBits: number, highBits: number}}
    */
   getVarint(index) {
-    let start = index;
+    this.cursor_ = index;
     let lowBits = 0;
     let highBits = 0;
 
     for (let shift = 0; shift < 28; shift += 7) {
-      const b = this.dataView_.getUint8(start++);
+      const b = this.dataView_.getUint8(this.cursor_++);
       lowBits |= (b & 0x7F) << shift;
       if ((b & 0x80) === 0) {
-        return {lowBits, highBits, dataStart: start};
+        return {lowBits, highBits};
       }
     }
 
-    const middleByte = this.dataView_.getUint8(start++);
+    const middleByte = this.dataView_.getUint8(this.cursor_++);
 
     // last four bits of the first 32 bit number
     lowBits |= (middleByte & 0x0F) << 28;
@@ -170,36 +194,100 @@
     highBits = (middleByte & 0x70) >> 4;
 
     if ((middleByte & 0x80) === 0) {
-      return {lowBits, highBits, dataStart: start};
+      return {lowBits, highBits};
     }
 
 
     for (let shift = 3; shift <= 31; shift += 7) {
-      const b = this.dataView_.getUint8(start++);
+      const b = this.dataView_.getUint8(this.cursor_++);
       highBits |= (b & 0x7F) << shift;
       if ((b & 0x80) === 0) {
-        return {lowBits, highBits, dataStart: start};
+        return {lowBits, highBits};
       }
     }
 
-    checkState(false, 'Data is longer than 10 bytes');
-    return {lowBits, highBits, dataStart: start};
+    checkCriticalState(false, 'Data is longer than 10 bytes');
+
+    return {lowBits, highBits};
   }
 
   /**
-   * Skips over a varint at a given index and returns the next position.
+   * Returns an unsigned int32 number at the current cursor position. The upper
+   * bits are discarded if the varint is longer than 32 bits. Also sets the
+   * cursor to the start of the next block of data.
+   * @return {number}
+   */
+  getUnsignedVarint32() {
+    let b = this.dataView_.getUint8(this.cursor_++);
+    let result = b & 0x7F;
+    if ((b & 0x80) === 0) {
+      return result;
+    }
+
+    b = this.dataView_.getUint8(this.cursor_++);
+    result |= (b & 0x7F) << 7;
+    if ((b & 0x80) === 0) {
+      return result;
+    }
+
+    b = this.dataView_.getUint8(this.cursor_++);
+    result |= (b & 0x7F) << 14;
+    if ((b & 0x80) === 0) {
+      return result;
+    }
+
+    b = this.dataView_.getUint8(this.cursor_++);
+    result |= (b & 0x7F) << 21;
+    if ((b & 0x80) === 0) {
+      return result;
+    }
+
+    // Extract only last 4 bits
+    b = this.dataView_.getUint8(this.cursor_++);
+    result |= (b & 0x0F) << 28;
+
+    for (let readBytes = 5; ((b & 0x80) !== 0) && readBytes < 10; readBytes++) {
+      b = this.dataView_.getUint8(this.cursor_++);
+    }
+
+    checkCriticalState((b & 0x80) === 0, 'Data is longer than 10 bytes');
+
+    // Result can be have 32 bits, convert it to unsigned
+    return result >>> 0;
+  }
+
+  /**
+   * Returns an unsigned int32 number at the specified index. The upper bits are
+   * discarded if the varint is longer than 32 bits. Also sets the cursor to the
+   * start of the next block of data.
+   * @param {number} index
+   * @return {number}
+   */
+  getUnsignedVarint32At(index) {
+    this.cursor_ = index;
+    return this.getUnsignedVarint32();
+  }
+
+  /**
+   * Seeks forward by the given amount.
+   * @param {number} skipAmount
+   * @package
+   */
+  skip(skipAmount) {
+    this.cursor_ += skipAmount;
+    checkCriticalPositionIndex(this.cursor_, this.endIndex_);
+  }
+
+  /**
+   * Skips over a varint at a given index.
    * @param {number} index Start of the data.
-   * @return {number} Position of the first byte after the varint.
    * @package
    */
   skipVarint(index) {
-    let cursor = index;
-    checkCriticalElementIndex(cursor, this.endIndex());
-    while (this.dataView_.getUint8(cursor++) & 0x80) {
-      checkCriticalElementIndex(cursor, this.endIndex());
+    this.cursor_ = index;
+    while (this.dataView_.getUint8(this.cursor_++) & 0x80) {
     }
-    checkCriticalPositionIndex(cursor, index + 10);
-    return cursor;
+    checkCriticalPositionIndex(this.cursor_, index + 10);
   }
 
   /**
diff --git a/js/experimental/runtime/kernel/buffer_decoder_test.js b/js/experimental/runtime/kernel/buffer_decoder_test.js
index aed045a..7c549f8 100644
--- a/js/experimental/runtime/kernel/buffer_decoder_test.js
+++ b/js/experimental/runtime/kernel/buffer_decoder_test.js
@@ -5,7 +5,7 @@
 goog.module('protobuf.binary.varintsTest');
 
 const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
-const {CHECK_CRITICAL_BOUNDS, CHECK_STATE} = goog.require('protobuf.internal.checks');
+const {CHECK_CRITICAL_STATE, CHECK_STATE} = goog.require('protobuf.internal.checks');
 
 goog.setTestOnly();
 
@@ -17,25 +17,47 @@
   return new Uint8Array(bytes).buffer;
 }
 
+describe('setCursor does', () => {
+  it('set the cursor at the position specified', () => {
+    const bufferDecoder =
+        BufferDecoder.fromArrayBuffer(createArrayBuffer(0x0, 0x1));
+    expect(bufferDecoder.cursor()).toBe(0);
+    bufferDecoder.setCursor(1);
+    expect(bufferDecoder.cursor()).toBe(1);
+  });
+});
+
+describe('skip does', () => {
+  it('advance the cursor', () => {
+    const bufferDecoder =
+        BufferDecoder.fromArrayBuffer(createArrayBuffer(0x0, 0x1, 0x2));
+    bufferDecoder.setCursor(1);
+    bufferDecoder.skip(1);
+    expect(bufferDecoder.cursor()).toBe(2);
+  });
+});
+
 describe('Skip varint does', () => {
   it('skip a varint', () => {
     const bufferDecoder =
         BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01));
-    expect(bufferDecoder.skipVarint(0)).toBe(1);
+    bufferDecoder.skipVarint(0);
+    expect(bufferDecoder.cursor()).toBe(1);
   });
 
   it('fail when varint is larger than 10 bytes', () => {
     const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(
         0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00));
 
-    if (CHECK_CRITICAL_BOUNDS) {
+    if (CHECK_CRITICAL_STATE) {
       expect(() => bufferDecoder.skipVarint(0)).toThrow();
     } else {
       // Note in unchecked mode we produce invalid output for invalid inputs.
       // This test just documents our behavior in those cases.
       // These values might change at any point and are not considered
       // what the implementation should be doing here.
-      expect(bufferDecoder.skipVarint(0)).toBe(11);
+      bufferDecoder.skipVarint(0);
+      expect(bufferDecoder.cursor()).toBe(11);
     }
   });
 
@@ -50,28 +72,144 @@
   it('read zero', () => {
     const bufferDecoder =
         BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00));
-    const {dataStart, lowBits, highBits} = bufferDecoder.getVarint(0);
-    expect(dataStart).toBe(1);
+    const {lowBits, highBits} = bufferDecoder.getVarint(0);
     expect(lowBits).toBe(0);
     expect(highBits).toBe(0);
+    expect(bufferDecoder.cursor()).toBe(1);
   });
 
   it('read one', () => {
     const bufferDecoder =
         BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01));
-    const {dataStart, lowBits, highBits} = bufferDecoder.getVarint(0);
-    expect(dataStart).toBe(1);
+    const {lowBits, highBits} = bufferDecoder.getVarint(0);
     expect(lowBits).toBe(1);
     expect(highBits).toBe(0);
+    expect(bufferDecoder.cursor()).toBe(1);
   });
 
   it('read max value', () => {
     const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(
         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01));
-    const {dataStart, lowBits, highBits} = bufferDecoder.getVarint(0);
-    expect(dataStart).toBe(10);
+    const {lowBits, highBits} = bufferDecoder.getVarint(0);
     expect(lowBits).toBe(-1);
     expect(highBits).toBe(-1);
+    expect(bufferDecoder.cursor()).toBe(10);
+  });
+});
+
+describe('readUnsignedVarint32 does', () => {
+  it('read zero', () => {
+    const bufferDecoder =
+        BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00));
+    const result = bufferDecoder.getUnsignedVarint32();
+    expect(result).toBe(0);
+    expect(bufferDecoder.cursor()).toBe(1);
+  });
+
+  it('read one', () => {
+    const bufferDecoder =
+        BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01));
+    const result = bufferDecoder.getUnsignedVarint32();
+    expect(result).toBe(1);
+    expect(bufferDecoder.cursor()).toBe(1);
+  });
+
+  it('read max int32', () => {
+    const bufferDecoder = BufferDecoder.fromArrayBuffer(
+        createArrayBuffer(0xFF, 0xFF, 0xFF, 0xFF, 0x0F));
+    const result = bufferDecoder.getUnsignedVarint32();
+    expect(result).toBe(4294967295);
+    expect(bufferDecoder.cursor()).toBe(5);
+  });
+
+  it('read max value', () => {
+    const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01));
+    const result = bufferDecoder.getUnsignedVarint32();
+    expect(result).toBe(4294967295);
+    expect(bufferDecoder.cursor()).toBe(10);
+  });
+
+  it('fail if data is longer than 10 bytes', () => {
+    const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01));
+    if (CHECK_CRITICAL_STATE) {
+      expect(() => bufferDecoder.getUnsignedVarint32()).toThrow();
+    } else {
+      // Note in unchecked mode we produce invalid output for invalid inputs.
+      // This test just documents our behavior in those cases.
+      // These values might change at any point and are not considered
+      // what the implementation should be doing here.
+      const result = bufferDecoder.getUnsignedVarint32();
+      expect(result).toBe(4294967295);
+      expect(bufferDecoder.cursor()).toBe(10);
+    }
+  });
+});
+
+describe('readUnsignedVarint32At does', () => {
+  it('reads from a specific index', () => {
+    const bufferDecoder =
+        BufferDecoder.fromArrayBuffer(createArrayBuffer(0x1, 0x2));
+    const result = bufferDecoder.getUnsignedVarint32At(1);
+    expect(result).toBe(2);
+    expect(bufferDecoder.cursor()).toBe(2);
+  });
+});
+
+describe('getFloat32 does', () => {
+  it('read one', () => {
+    const bufferDecoder = BufferDecoder.fromArrayBuffer(
+        createArrayBuffer(0x00, 0x00, 0x80, 0x3F));
+    const result = bufferDecoder.getFloat32(0);
+    expect(result).toBe(1);
+    expect(bufferDecoder.cursor()).toBe(4);
+  });
+});
+
+describe('getFloat64 does', () => {
+  it('read one', () => {
+    const bufferDecoder = BufferDecoder.fromArrayBuffer(
+        createArrayBuffer(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F));
+    const result = bufferDecoder.getFloat64(0);
+    expect(result).toBe(1);
+    expect(bufferDecoder.cursor()).toBe(8);
+  });
+});
+
+describe('getInt32 does', () => {
+  it('read one', () => {
+    const bufferDecoder = BufferDecoder.fromArrayBuffer(
+        createArrayBuffer(0x01, 0x00, 0x00, 0x00));
+    const result = bufferDecoder.getInt32(0);
+    expect(result).toBe(1);
+    expect(bufferDecoder.cursor()).toBe(4);
+  });
+
+  it('read minus one', () => {
+    const bufferDecoder = BufferDecoder.fromArrayBuffer(
+        createArrayBuffer(0xFF, 0xFF, 0xFF, 0xFF));
+    const result = bufferDecoder.getInt32(0);
+    expect(result).toBe(-1);
+    expect(bufferDecoder.cursor()).toBe(4);
+  });
+});
+
+describe('getUint32 does', () => {
+  it('read one', () => {
+    const bufferDecoder =
+        BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01, 0x00, 0x00, 0x0));
+    const result = bufferDecoder.getUint32(0);
+    expect(result).toBe(1);
+    expect(bufferDecoder.cursor()).toBe(4);
+  });
+
+  it('read max uint32', () => {
+    const bufferDecoder = BufferDecoder.fromArrayBuffer(
+        createArrayBuffer(0xFF, 0xFF, 0xFF, 0xFF));
+    const result = bufferDecoder.getUint32(0);
+    expect(result).toBe(4294967295);
+    expect(bufferDecoder.cursor()).toBe(4);
   });
 });
 
diff --git a/js/experimental/runtime/kernel/indexer.js b/js/experimental/runtime/kernel/indexer.js
index c247c2f..e281994 100644
--- a/js/experimental/runtime/kernel/indexer.js
+++ b/js/experimental/runtime/kernel/indexer.js
@@ -8,7 +8,7 @@
 const Storage = goog.require('protobuf.binary.Storage');
 const WireType = goog.require('protobuf.binary.WireType');
 const {Field} = goog.require('protobuf.binary.field');
-const {checkCriticalPositionIndex, checkCriticalState} = goog.require('protobuf.internal.checks');
+const {checkCriticalElementIndex, checkCriticalState} = goog.require('protobuf.internal.checks');
 
 /**
  * Appends a new entry in the index array for the given field number.
@@ -57,8 +57,6 @@
   constructor(bufferDecoder) {
     /** @private @const {!BufferDecoder} */
     this.bufferDecoder_ = bufferDecoder;
-    /** @private {number} */
-    this.cursor_ = bufferDecoder.startIndex();
   }
 
   /**
@@ -66,15 +64,18 @@
    * @return {!Storage<!Field>}
    */
   index(pivot) {
+    this.bufferDecoder_.setCursor(this.bufferDecoder_.startIndex());
+
     const storage = new Storage(pivot);
-    while (this.hasNextByte_()) {
-      const tag = this.readVarInt32_();
+    while (this.bufferDecoder_.hasNext()) {
+      const tag = this.bufferDecoder_.getUnsignedVarint32();
       const wireType = tagToWireType(tag);
       const fieldNumber = tagToFieldNumber(tag);
       checkCriticalState(
           fieldNumber > 0, `Invalid field number ${fieldNumber}`);
 
-      addIndexEntry(storage, fieldNumber, wireType, this.cursor_);
+      addIndexEntry(
+          storage, fieldNumber, wireType, this.bufferDecoder_.cursor());
 
       checkCriticalState(
           !this.skipField_(wireType, fieldNumber),
@@ -93,14 +94,18 @@
   skipField_(wireType, fieldNumber) {
     switch (wireType) {
       case WireType.VARINT:
-        this.cursor_ = this.bufferDecoder_.skipVarint(this.cursor_);
+        checkCriticalElementIndex(
+            this.bufferDecoder_.cursor(), this.bufferDecoder_.endIndex());
+        this.bufferDecoder_.skipVarint(this.bufferDecoder_.cursor());
         return false;
       case WireType.FIXED64:
-        this.skip_(8);
+        this.bufferDecoder_.skip(8);
         return false;
       case WireType.DELIMITED:
-        const length = this.readVarInt32_();
-        this.skip_(length);
+        checkCriticalElementIndex(
+            this.bufferDecoder_.cursor(), this.bufferDecoder_.endIndex());
+        const length = this.bufferDecoder_.getUnsignedVarint32();
+        this.bufferDecoder_.skip(length);
         return false;
       case WireType.START_GROUP:
         checkCriticalState(this.skipGroup_(fieldNumber), 'No end group found.');
@@ -109,7 +114,7 @@
         // Signal that we found a stop group to the caller
         return true;
       case WireType.FIXED32:
-        this.skip_(4);
+        this.bufferDecoder_.skip(4);
         return false;
       default:
         throw new Error(`Invalid wire type: ${wireType}`);
@@ -117,16 +122,6 @@
   }
 
   /**
-   * Seeks forward by the given amount.
-   * @param {number} skipAmount
-   * @private
-   */
-  skip_(skipAmount) {
-    this.cursor_ += skipAmount;
-    checkCriticalPositionIndex(this.cursor_, this.bufferDecoder_.endIndex());
-  }
-
-  /**
    * Skips over fields until it finds the end of a given group.
    * @param {number} groupFieldNumber
    * @return {boolean} Returns true if an end was found.
@@ -138,8 +133,8 @@
     // Note: Since we are calling skipField from here nested groups will be
     // handled by recursion of this method and thus we will not see a nested
     // STOP GROUP here unless there is something wrong with the input data.
-    while (this.hasNextByte_()) {
-      const tag = this.readVarInt32_();
+    while (this.bufferDecoder_.hasNext()) {
+      const tag = this.bufferDecoder_.getUnsignedVarint32();
       const wireType = tagToWireType(tag);
       const fieldNumber = tagToFieldNumber(tag);
 
@@ -153,26 +148,6 @@
     }
     return false;
   }
-
-  /**
-   * Returns a JS number for a 32 bit var int.
-   * @return {number}
-   * @private
-   */
-  readVarInt32_() {
-    const {lowBits, dataStart} = this.bufferDecoder_.getVarint(this.cursor_);
-    this.cursor_ = dataStart;
-    return lowBits;
-  }
-
-  /**
-   * Returns true if there are more bytes to read in the array.
-   * @return {boolean}
-   * @private
-   */
-  hasNextByte_() {
-    return this.cursor_ < this.bufferDecoder_.endIndex();
-  }
 }
 
 /**
@@ -186,7 +161,6 @@
   return new Indexer(bufferDecoder).index(pivot);
 }
 
-
 exports = {
   buildIndex,
 };
diff --git a/js/experimental/runtime/kernel/lazy_accessor.js b/js/experimental/runtime/kernel/lazy_accessor.js
index cebf0c0..fe1f8ef 100644
--- a/js/experimental/runtime/kernel/lazy_accessor.js
+++ b/js/experimental/runtime/kernel/lazy_accessor.js
@@ -808,8 +808,10 @@
    * @return {!Iterable<boolean>}
    */
   getRepeatedBoolIterable(fieldNumber) {
-    const array = this.getRepeatedBoolArray_(fieldNumber);
-    return new ArrayIterable(array);
+    // Don't split this statement unless needed. JS compiler thinks
+    // getRepeatedBoolArray_ might have side effects and doesn't inline the
+    // call in the compiled code. See cl/293894484 for details.
+    return new ArrayIterable(this.getRepeatedBoolArray_(fieldNumber));
   }
 
   /**
@@ -857,8 +859,10 @@
    * @return {!Iterable<number>}
    */
   getRepeatedDoubleIterable(fieldNumber) {
-    const array = this.getRepeatedDoubleArray_(fieldNumber);
-    return new ArrayIterable(array);
+    // Don't split this statement unless needed. JS compiler thinks
+    // getRepeatedDoubleArray_ might have side effects and doesn't inline the
+    // call in the compiled code. See cl/293894484 for details.
+    return new ArrayIterable(this.getRepeatedDoubleArray_(fieldNumber));
   }
 
   /**
@@ -906,8 +910,10 @@
    * @return {!Iterable<number>}
    */
   getRepeatedFixed32Iterable(fieldNumber) {
-    const array = this.getRepeatedFixed32Array_(fieldNumber);
-    return new ArrayIterable(array);
+    // Don't split this statement unless needed. JS compiler thinks
+    // getRepeatedFixed32Array_ might have side effects and doesn't inline the
+    // call in the compiled code. See cl/293894484 for details.
+    return new ArrayIterable(this.getRepeatedFixed32Array_(fieldNumber));
   }
 
   /**
@@ -986,8 +992,10 @@
    * @return {!Iterable<number>}
    */
   getRepeatedFloatIterable(fieldNumber) {
-    const array = this.getRepeatedFloatArray_(fieldNumber);
-    return new ArrayIterable(array);
+    // Don't split this statement unless needed. JS compiler thinks
+    // getRepeatedFloatArray_ might have side effects and doesn't inline the
+    // call in the compiled code. See cl/293894484 for details.
+    return new ArrayIterable(this.getRepeatedFloatArray_(fieldNumber));
   }
 
   /**
@@ -1035,8 +1043,10 @@
    * @return {!Iterable<number>}
    */
   getRepeatedInt32Iterable(fieldNumber) {
-    const array = this.getRepeatedInt32Array_(fieldNumber);
-    return new ArrayIterable(array);
+    // Don't split this statement unless needed. JS compiler thinks
+    // getRepeatedInt32Array_ might have side effects and doesn't inline the
+    // call in the compiled code. See cl/293894484 for details.
+    return new ArrayIterable(this.getRepeatedInt32Array_(fieldNumber));
   }
 
   /**
@@ -1084,8 +1094,10 @@
    * @return {!Iterable<!Int64>}
    */
   getRepeatedInt64Iterable(fieldNumber) {
-    const array = this.getRepeatedInt64Array_(fieldNumber);
-    return new ArrayIterable(array);
+    // Don't split this statement unless needed. JS compiler thinks
+    // getRepeatedInt64Array_ might have side effects and doesn't inline the
+    // call in the compiled code. See cl/293894484 for details.
+    return new ArrayIterable(this.getRepeatedInt64Array_(fieldNumber));
   }
 
   /**
@@ -1133,8 +1145,10 @@
    * @return {!Iterable<number>}
    */
   getRepeatedSfixed32Iterable(fieldNumber) {
-    const array = this.getRepeatedSfixed32Array_(fieldNumber);
-    return new ArrayIterable(array);
+    // Don't split this statement unless needed. JS compiler thinks
+    // getRepeatedSfixed32Array_ might have side effects and doesn't inline the
+    // call in the compiled code. See cl/293894484 for details.
+    return new ArrayIterable(this.getRepeatedSfixed32Array_(fieldNumber));
   }
 
   /**
@@ -1182,8 +1196,10 @@
    * @return {!Iterable<!Int64>}
    */
   getRepeatedSfixed64Iterable(fieldNumber) {
-    const array = this.getRepeatedSfixed64Array_(fieldNumber);
-    return new ArrayIterable(array);
+    // Don't split this statement unless needed. JS compiler thinks
+    // getRepeatedSfixed64Array_ might have side effects and doesn't inline the
+    // call in the compiled code. See cl/293894484 for details.
+    return new ArrayIterable(this.getRepeatedSfixed64Array_(fieldNumber));
   }
 
   /**
@@ -1231,8 +1247,10 @@
    * @return {!Iterable<number>}
    */
   getRepeatedSint32Iterable(fieldNumber) {
-    const array = this.getRepeatedSint32Array_(fieldNumber);
-    return new ArrayIterable(array);
+    // Don't split this statement unless needed. JS compiler thinks
+    // getRepeatedSint32Array_ might have side effects and doesn't inline the
+    // call in the compiled code. See cl/293894484 for details.
+    return new ArrayIterable(this.getRepeatedSint32Array_(fieldNumber));
   }
 
   /**
@@ -1280,8 +1298,10 @@
    * @return {!Iterable<!Int64>}
    */
   getRepeatedSint64Iterable(fieldNumber) {
-    const array = this.getRepeatedSint64Array_(fieldNumber);
-    return new ArrayIterable(array);
+    // Don't split this statement unless needed. JS compiler thinks
+    // getRepeatedSint64Array_ might have side effects and doesn't inline the
+    // call in the compiled code. See cl/293894484 for details.
+    return new ArrayIterable(this.getRepeatedSint64Array_(fieldNumber));
   }
 
   /**
@@ -1329,8 +1349,10 @@
    * @return {!Iterable<number>}
    */
   getRepeatedUint32Iterable(fieldNumber) {
-    const array = this.getRepeatedUint32Array_(fieldNumber);
-    return new ArrayIterable(array);
+    // Don't split this statement unless needed. JS compiler thinks
+    // getRepeatedUint32Array_ might have side effects and doesn't inline the
+    // call in the compiled code. See cl/293894484 for details.
+    return new ArrayIterable(this.getRepeatedUint32Array_(fieldNumber));
   }
 
   /**
@@ -1408,8 +1430,10 @@
    * @return {!Iterable<!ByteString>}
    */
   getRepeatedBytesIterable(fieldNumber) {
-    const array = this.getRepeatedBytesArray_(fieldNumber);
-    return new ArrayIterable(array);
+    // Don't split this statement unless needed. JS compiler thinks
+    // getRepeatedBytesArray_ might have side effects and doesn't inline the
+    // call in the compiled code. See cl/293894484 for details.
+    return new ArrayIterable(this.getRepeatedBytesArray_(fieldNumber));
   }
 
   /**
@@ -1456,8 +1480,10 @@
    * @return {!Iterable<string>}
    */
   getRepeatedStringIterable(fieldNumber) {
-    const array = this.getRepeatedStringArray_(fieldNumber);
-    return new ArrayIterable(array);
+    // Don't split this statement unless needed. JS compiler thinks
+    // getRepeatedStringArray_ might have side effects and doesn't inline the
+    // call in the compiled code. See cl/293894484 for details.
+    return new ArrayIterable(this.getRepeatedStringArray_(fieldNumber));
   }
 
   /**
@@ -1482,18 +1508,35 @@
    * @private
    */
   getRepeatedMessageArray_(fieldNumber, instanceCreator, pivot) {
+    // This method can be shortened using getFieldWithDefault and
+    // getRepeatedNonPrimitive methods. But that will require creating and
+    // passing a reader closure every time getRepeatedMessageArray_ is called,
+    // which is expensive.
     checkInstanceCreator(instanceCreator);
-    const bytesInstanceCreator = (bufferDecoder) =>
-        instanceCreator(LazyAccessor.fromBufferDecoder_(bufferDecoder, pivot));
-    const readMessageFunc = (bufferDecoder, start) =>
-        bytesInstanceCreator(reader.readDelimited(bufferDecoder, start));
+    checkFieldNumber(fieldNumber);
 
-    const readRepeatedMessageFunc = (indexArray, bufferDecoder) =>
-        readRepeatedNonPrimitive(indexArray, bufferDecoder, readMessageFunc);
-    const encoder = (writer, fieldNumber, values) =>
-        writeRepeatedMessage(writer, fieldNumber, values);
-    return this.getFieldWithDefault_(
-        fieldNumber, /* defaultValue= */[], readRepeatedMessageFunc, encoder);
+    const field = this.fields_.get(fieldNumber);
+    if (field === undefined) {
+      return [];
+    }
+
+    if (field.hasDecodedValue()) {
+      return field.getDecodedValue();
+    }
+
+    const indexArray = checkDefAndNotNull(field.getIndexArray());
+    const result = new Array(indexArray.length);
+    for (let i = 0; i < indexArray.length; i++) {
+      validateWireType(indexArray[i], WireType.DELIMITED);
+      const subMessageBuffer = reader.readDelimited(
+          checkDefAndNotNull(this.bufferDecoder_),
+          Field.getStartIndex(indexArray[i]));
+      result[i] = instanceCreator(
+          LazyAccessor.fromBufferDecoder_(subMessageBuffer, pivot));
+    }
+    field.setCache(result, writeRepeatedMessage);
+
+    return result;
   }
 
   /**
@@ -1523,9 +1566,11 @@
    * @template T
    */
   getRepeatedMessageIterable(fieldNumber, instanceCreator, pivot = undefined) {
-    const array =
-        this.getRepeatedMessageArray_(fieldNumber, instanceCreator, pivot);
-    return new ArrayIterable(array);
+    // Don't split this statement unless needed. JS compiler thinks
+    // getRepeatedMessageArray_ might have side effects and doesn't inline the
+    // call in the compiled code. See cl/293894484 for details.
+    return new ArrayIterable(
+        this.getRepeatedMessageArray_(fieldNumber, instanceCreator, pivot));
   }
 
   /**
diff --git a/js/experimental/runtime/kernel/reader.js b/js/experimental/runtime/kernel/reader.js
index fec79cf..2b80e15 100644
--- a/js/experimental/runtime/kernel/reader.js
+++ b/js/experimental/runtime/kernel/reader.js
@@ -6,6 +6,7 @@
 const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
 const ByteString = goog.require('protobuf.ByteString');
 const Int64 = goog.require('protobuf.Int64');
+const {checkState} = goog.require('protobuf.internal.checks');
 
 
 /******************************************************************************
@@ -13,18 +14,6 @@
  ******************************************************************************/
 
 /**
- * Reads a boolean from the binary bytes.
- * Also returns the first position after the boolean.
- * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
- * @param {number} index Start of the data.
- * @return {{value: boolean, nextCursor: number}}
- */
-function readBoolValue(bufferDecoder, index) {
-  const {lowBits, highBits, dataStart} = bufferDecoder.getVarint(index);
-  return {value: lowBits !== 0 || highBits !== 0, nextCursor: dataStart};
-}
-
-/**
  * Reads a boolean value from the binary bytes.
  * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
  * @param {number} start Start of the data.
@@ -32,11 +21,12 @@
  * @package
  */
 function readBool(bufferDecoder, start) {
-  return readBoolValue(bufferDecoder, start).value;
+  const {lowBits, highBits} = bufferDecoder.getVarint(start);
+  return lowBits !== 0 || highBits !== 0;
 }
 
 /**
- * Reads a double value from the binary bytes.
+ * Reads a ByteString value from the binary bytes.
  * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
  * @param {number} start Start of the data.
  * @return {!ByteString}
@@ -49,39 +39,15 @@
 /**
  * Reads a int32 value from the binary bytes encoded as varint.
  * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
- * @param {number} index Start of the data.
- * @return {{value: number, nextCursor: number}}
- * @package
- */
-function readInt32Value(bufferDecoder, index) {
-  const {lowBits, dataStart} = bufferDecoder.getVarint(index);
-  // Negative 32 bit integers are encoded with 64 bit values.
-  // Clients are expected to truncate back to 32 bits.
-  // This is why we are dropping the upper bytes here.
-  return {value: lowBits | 0, nextCursor: dataStart};
-}
-
-/**
- * Reads a int32 value from the binary bytes encoded as varint.
- * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
  * @param {number} start Start of the data.
  * @return {number}
  * @package
  */
 function readInt32(bufferDecoder, start) {
-  return readInt32Value(bufferDecoder, start).value;
-}
-
-/**
- * Reads a int32 value from the binary bytes encoded as varint.
- * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
- * @param {number} index Start of the data.
- * @return {{ value: !Int64, nextCursor: number}}
- * @package
- */
-function readInt64Value(bufferDecoder, index) {
-  const {lowBits, highBits, dataStart} = bufferDecoder.getVarint(index);
-  return {value: Int64.fromBits(lowBits, highBits), nextCursor: dataStart};
+  // Negative 32 bit integers are encoded with 64 bit values.
+  // Clients are expected to truncate back to 32 bits.
+  // This is why we are dropping the upper bytes here.
+  return bufferDecoder.getUnsignedVarint32At(start) | 0;
 }
 
 /**
@@ -92,7 +58,8 @@
  * @package
  */
 function readInt64(bufferDecoder, start) {
-  return readInt64Value(bufferDecoder, start).value;
+  const {lowBits, highBits} = bufferDecoder.getVarint(start);
+  return Int64.fromBits(lowBits, highBits);
 }
 
 /**
@@ -132,45 +99,15 @@
 
 /**
  * Reads a sint32 value from the binary bytes encoded as varint.
- * Also returns the first position after the boolean.
- * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
- * @param {number} index Start of the data.
- * @return {{value: number, nextCursor: number}}
- */
-function readSint32Value(bufferDecoder, index) {
-  const {lowBits, dataStart} = bufferDecoder.getVarint(index);
-  // Truncate upper bits and convert from zig zag to signd int
-  return {value: (lowBits >>> 1) ^ -(lowBits & 0x01), nextCursor: dataStart};
-}
-
-/**
- * Reads a sint32 value from the binary bytes encoded as varint.
  * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
  * @param {number} start Start of the data.
  * @return {number}
  * @package
  */
 function readSint32(bufferDecoder, start) {
-  return readSint32Value(bufferDecoder, start).value;
-}
-
-/**
- * Reads a sint64 value from the binary bytes encoded as varint.
- * Also returns the first position after the value.
- * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
- * @param {number} index Start of the data.
- * @return {{value: !Int64, nextCursor: number}}
- * @package
- */
-function readSint64Value(bufferDecoder, index) {
-  const {lowBits, highBits, dataStart} = bufferDecoder.getVarint(index);
-  const sign = -(lowBits & 0x01);
-  const decodedLowerBits = ((lowBits >>> 1) | (highBits & 0x01) << 31) ^ sign;
-  const decodedUpperBits = (highBits >>> 1) ^ sign;
-  return {
-    value: Int64.fromBits(decodedLowerBits, decodedUpperBits),
-    nextCursor: dataStart
-  };
+  const bits = bufferDecoder.getUnsignedVarint32At(start);
+  // Truncate upper bits and convert from zig zag to signd int
+  return (bits >>> 1) ^ -(bits & 0x01);
 }
 
 /**
@@ -181,7 +118,11 @@
  * @package
  */
 function readSint64(bufferDecoder, start) {
-  return readSint64Value(bufferDecoder, start).value;
+  const {lowBits, highBits} = bufferDecoder.getVarint(start);
+  const sign = -(lowBits & 0x01);
+  const decodedLowerBits = ((lowBits >>> 1) | (highBits & 0x01) << 31) ^ sign;
+  const decodedUpperBits = (highBits >>> 1) ^ sign;
+  return Int64.fromBits(decodedLowerBits, decodedUpperBits);
 }
 
 /**
@@ -192,9 +133,8 @@
  * @package
  */
 function readDelimited(bufferDecoder, start) {
-  const {lowBits, dataStart} = bufferDecoder.getVarint(start);
-  const unsignedLength = lowBits >>> 0;
-  return bufferDecoder.subBufferDecoder(dataStart, unsignedLength);
+  const unsignedLength = bufferDecoder.getUnsignedVarint32At(start);
+  return bufferDecoder.subBufferDecoder(bufferDecoder.cursor(), unsignedLength);
 }
 
 /**
@@ -210,25 +150,13 @@
 
 /**
  * Reads a uint32 value from the binary bytes encoded as varint.
- * Also returns the first position after the value.
- * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
- * @param {number} index Start of the data.
- * @return {{value: number, nextCursor: number}}
- */
-function readUint32Value(bufferDecoder, index) {
-  const {lowBits, dataStart} = bufferDecoder.getVarint(index);
-  return {value: lowBits >>> 0, nextCursor: dataStart};
-}
-
-/**
- * Reads a uint32 value from the binary bytes encoded as varint.
  * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
  * @param {number} start Start of the data.
  * @return {number}
  * @package
  */
 function readUint32(bufferDecoder, start) {
-  return readUint32Value(bufferDecoder, start).value;
+  return bufferDecoder.getUnsignedVarint32At(start);
 }
 
 /**
@@ -266,7 +194,7 @@
  * @package
  */
 function readPackedBool(bufferDecoder, start) {
-  return readPackedVariableLength(bufferDecoder, start, readBoolValue);
+  return readPacked(bufferDecoder, start, readBool);
 }
 
 /**
@@ -278,7 +206,7 @@
  * @package
  */
 function readPackedDouble(bufferDecoder, start) {
-  return readPackedFixed(bufferDecoder, start, 8, readDouble);
+  return readPacked(bufferDecoder, start, readDouble);
 }
 
 /**
@@ -290,7 +218,7 @@
  * @package
  */
 function readPackedFixed32(bufferDecoder, start) {
-  return readPackedFixed(bufferDecoder, start, 4, readFixed32);
+  return readPacked(bufferDecoder, start, readFixed32);
 }
 
 /**
@@ -302,7 +230,7 @@
  * @package
  */
 function readPackedFloat(bufferDecoder, start) {
-  return readPackedFixed(bufferDecoder, start, 4, readFloat);
+  return readPacked(bufferDecoder, start, readFloat);
 }
 
 /**
@@ -314,7 +242,7 @@
  * @package
  */
 function readPackedInt32(bufferDecoder, start) {
-  return readPackedVariableLength(bufferDecoder, start, readInt32Value);
+  return readPacked(bufferDecoder, start, readInt32);
 }
 
 /**
@@ -326,7 +254,7 @@
  * @package
  */
 function readPackedInt64(bufferDecoder, start) {
-  return readPackedVariableLength(bufferDecoder, start, readInt64Value);
+  return readPacked(bufferDecoder, start, readInt64);
 }
 
 /**
@@ -338,7 +266,7 @@
  * @package
  */
 function readPackedSfixed32(bufferDecoder, start) {
-  return readPackedFixed(bufferDecoder, start, 4, readSfixed32);
+  return readPacked(bufferDecoder, start, readSfixed32);
 }
 
 /**
@@ -350,7 +278,7 @@
  * @package
  */
 function readPackedSfixed64(bufferDecoder, start) {
-  return readPackedFixed(bufferDecoder, start, 8, readSfixed64);
+  return readPacked(bufferDecoder, start, readSfixed64);
 }
 
 /**
@@ -362,7 +290,7 @@
  * @package
  */
 function readPackedSint32(bufferDecoder, start) {
-  return readPackedVariableLength(bufferDecoder, start, readSint32Value);
+  return readPacked(bufferDecoder, start, readSint32);
 }
 
 /**
@@ -374,7 +302,7 @@
  * @package
  */
 function readPackedSint64(bufferDecoder, start) {
-  return readPackedVariableLength(bufferDecoder, start, readSint64Value);
+  return readPacked(bufferDecoder, start, readSint64);
 }
 
 /**
@@ -386,51 +314,25 @@
  * @package
  */
 function readPackedUint32(bufferDecoder, start) {
-  return readPackedVariableLength(bufferDecoder, start, readUint32Value);
+  return readPacked(bufferDecoder, start, readUint32);
 }
 
 /**
- * Read packed variable length values.
+ * Read packed values.
  * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
  * @param {number} start Start of the data.
- * @param {function(!BufferDecoder, number):{value:T, nextCursor: number}}
- *     valueFunction
- * @return {!Array<T>}
- * @package
- * @template T
- */
-function readPackedVariableLength(bufferDecoder, start, valueFunction) {
-  const /** !Array<T> */ result = [];
-  const {lowBits, dataStart} = bufferDecoder.getVarint(start);
-  let cursor = dataStart;
-  const unsignedLength = lowBits >>> 0;
-  while (cursor < dataStart + unsignedLength) {
-    const {value, nextCursor} = valueFunction(bufferDecoder, cursor);
-    cursor = nextCursor;
-    result.push(value);
-  }
-  return result;
-}
-
-/**
- * Read a packed fixed values.
- * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
- * @param {number} start Start of the data.
- * @param {number} size End of the data.
  * @param {function(!BufferDecoder, number):T} valueFunction
  * @return {!Array<T>}
  * @package
  * @template T
  */
-function readPackedFixed(bufferDecoder, start, size, valueFunction) {
-  const {lowBits, dataStart} = bufferDecoder.getVarint(start);
-  const unsignedLength = lowBits >>> 0;
-  const noOfEntries = unsignedLength / size;
-  const /** !Array<T> */ result = new Array(noOfEntries);
-  let cursor = dataStart;
-  for (let i = 0; i < noOfEntries; i++) {
-    result[i] = valueFunction(bufferDecoder, cursor);
-    cursor += size;
+function readPacked(bufferDecoder, start, valueFunction) {
+  const /** !Array<T> */ result = [];
+  const unsignedLength = bufferDecoder.getUnsignedVarint32At(start);
+  const dataStart = bufferDecoder.cursor();
+  while (bufferDecoder.cursor() < dataStart + unsignedLength) {
+    checkState(bufferDecoder.cursor() > 0);
+    result.push(valueFunction(bufferDecoder, bufferDecoder.cursor()));
   }
   return result;
 }
diff --git a/js/experimental/runtime/kernel/reader_test.js b/js/experimental/runtime/kernel/reader_test.js
index a0cbcae..dd02086 100644
--- a/js/experimental/runtime/kernel/reader_test.js
+++ b/js/experimental/runtime/kernel/reader_test.js
@@ -12,7 +12,7 @@
 const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
 const ByteString = goog.require('protobuf.ByteString');
 const reader = goog.require('protobuf.binary.reader');
-const {CHECK_STATE} = goog.require('protobuf.internal.checks');
+const {CHECK_CRITICAL_STATE} = goog.require('protobuf.internal.checks');
 const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
 const {encode} = goog.require('protobuf.binary.textencoding');
 const {getBoolPairs} = goog.require('protobuf.binary.boolTestPairs');
@@ -45,7 +45,7 @@
 describe('Read bool does', () => {
   for (const pair of getBoolPairs()) {
     it(`decode ${pair.name}`, () => {
-      if (pair.error && CHECK_STATE) {
+      if (pair.error && CHECK_CRITICAL_STATE) {
         expect(() => reader.readBool(pair.bufferDecoder, 0)).toThrow();
       } else {
         const d = reader.readBool(
@@ -120,7 +120,7 @@
 
   for (const pair of getInt32Pairs()) {
     it(`decode ${pair.name}`, () => {
-      if (pair.error && CHECK_STATE) {
+      if (pair.error && CHECK_CRITICAL_STATE) {
         expect(() => reader.readInt32(pair.bufferDecoder, 0)).toThrow();
       } else {
         const d = reader.readInt32(pair.bufferDecoder, 0);
@@ -166,7 +166,7 @@
 
   for (const pair of getSint32Pairs()) {
     it(`decode ${pair.name}`, () => {
-      if (pair.error && CHECK_STATE) {
+      if (pair.error && CHECK_CRITICAL_STATE) {
         expect(() => reader.readSint32(pair.bufferDecoder, 0)).toThrow();
       } else {
         const d = reader.readSint32(pair.bufferDecoder, 0);
@@ -184,7 +184,7 @@
 
   for (const pair of getInt64Pairs()) {
     it(`decode ${pair.name}`, () => {
-      if (pair.error && CHECK_STATE) {
+      if (pair.error && CHECK_CRITICAL_STATE) {
         expect(() => reader.readInt64(pair.bufferDecoder, 0)).toThrow();
       } else {
         const d = reader.readInt64(pair.bufferDecoder, 0);
@@ -202,7 +202,7 @@
 
   for (const pair of getSint64Pairs()) {
     it(`decode ${pair.name}`, () => {
-      if (pair.error && CHECK_STATE) {
+      if (pair.error && CHECK_CRITICAL_STATE) {
         expect(() => reader.readSint64(pair.bufferDecoder, 0)).toThrow();
       } else {
         const d = reader.readSint64(pair.bufferDecoder, 0);
@@ -220,7 +220,7 @@
 
   for (const pair of getUint32Pairs()) {
     it(`decode ${pair.name}`, () => {
-      if (pair.error && CHECK_STATE) {
+      if (pair.error && CHECK_CRITICAL_STATE) {
         expect(() => reader.readUint32(pair.bufferDecoder, 0)).toThrow();
       } else {
         const d = reader.readUint32(pair.bufferDecoder, 0);
diff --git a/js/experimental/runtime/kernel/writer.js b/js/experimental/runtime/kernel/writer.js
index 1fc7418..73f852e 100644
--- a/js/experimental/runtime/kernel/writer.js
+++ b/js/experimental/runtime/kernel/writer.js
@@ -93,7 +93,7 @@
     checkFieldNumber(fieldNumber);
     checkWireType(wireType);
     const tag = fieldNumber << 3 | wireType;
-    this.writeUnsignedVarint32_(tag);
+    this.writeUnsignedVarint32_(tag >>> 0);
   }
 
   /**
@@ -450,12 +450,13 @@
   getLength_(bufferDecoder, start, wireType) {
     switch (wireType) {
       case WireType.VARINT:
-        return bufferDecoder.skipVarint(start) - start;
+        bufferDecoder.skipVarint(start);
+        return bufferDecoder.cursor() - start;
       case WireType.FIXED64:
         return 8;
       case WireType.DELIMITED:
-        const {lowBits: dataLength, dataStart} = bufferDecoder.getVarint(start);
-        return dataLength + dataStart - start;
+        const dataLength = bufferDecoder.getUnsignedVarint32At(start);
+        return dataLength + bufferDecoder.cursor() - start;
       case WireType.START_GROUP:
         return this.getGroupLength_(bufferDecoder, start);
       case WireType.FIXED32:
@@ -477,12 +478,13 @@
     // corresponding stop group
     let cursor = start;
     while (cursor < bufferDecoder.endIndex()) {
-      const {lowBits: tag, dataStart} = bufferDecoder.getVarint(cursor);
+      const tag = bufferDecoder.getUnsignedVarint32At(cursor);
       const wireType = /** @type {!WireType} */ (tag & 0x07);
       if (wireType === WireType.END_GROUP) {
-        return dataStart - start;
+        return bufferDecoder.cursor() - start;
       }
-      cursor = dataStart + this.getLength_(bufferDecoder, dataStart, wireType);
+      cursor = bufferDecoder.cursor() +
+          this.getLength_(bufferDecoder, bufferDecoder.cursor(), wireType);
     }
     throw new Error('No end group found');
   }
diff --git a/js/experimental/runtime/kernel/writer_test.js b/js/experimental/runtime/kernel/writer_test.js
index e4b2184..331ab2b 100644
--- a/js/experimental/runtime/kernel/writer_test.js
+++ b/js/experimental/runtime/kernel/writer_test.js
@@ -60,6 +60,18 @@
     const writer = new Writer();
     writer.writeTag(1, WireType.VARINT);
     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0x08));
+
+    writer.writeTag(0x0FFFFFFF, WireType.VARINT);
+    expect(writer.getAndResetResultBuffer())
+        .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0x7));
+
+    writer.writeTag(0x10000000, WireType.VARINT);
+    expect(writer.getAndResetResultBuffer())
+        .toEqual(createArrayBuffer(0x80, 0x80, 0x80, 0x80, 0x08));
+
+    writer.writeTag(0x1FFFFFFF, WireType.VARINT);
+    expect(writer.getAndResetResultBuffer())
+        .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0x0F));
   });
 
   it('reset after calling getAndResetResultBuffer', () => {
@@ -95,7 +107,8 @@
       // These values might change at any point and are not considered
       // what the implementation should be doing here.
       writer.writeTag(-1, WireType.VARINT);
-      expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0xF8));
+      expect(writer.getAndResetResultBuffer())
+          .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0xF));
     }
   });
 
@@ -504,7 +517,11 @@
       expect(new Uint8Array(writer.getAndResetResultBuffer()))
           .toEqual(new Uint8Array(createArrayBuffer(
               -6,  // invalid tag
-              1,   // string length
+              0xff,
+              0xff,
+              0xff,
+              0x0f,
+              1,  // string length
               'a'.charCodeAt(0),
               )));
     }
diff --git a/js/gulpfile.js b/js/gulpfile.js
index 1f0946c..a81c011 100644
--- a/js/gulpfile.js
+++ b/js/gulpfile.js
@@ -37,6 +37,7 @@
   'testbinary.proto',
   'testempty.proto',
   'test.proto',
+  'testlargenumbers.proto',
 ];
 
 var group2Protos = [
diff --git a/js/message.js b/js/message.js
index 5c08112..c1736b3 100644
--- a/js/message.js
+++ b/js/message.js
@@ -1112,8 +1112,11 @@
   goog.asserts.assertInstanceof(msg, jspb.Message);
   if (value !== defaultValue) {
     jspb.Message.setField(msg, fieldNumber, value);
-  } else {
+  } else if (fieldNumber < msg.pivot_) {
     msg.array[jspb.Message.getIndex_(msg, fieldNumber)] = null;
+  } else {
+    jspb.Message.maybeInitEmptyExtensionObject_(msg);
+    delete msg.extensionObject_[fieldNumber];
   }
   return msg;
 };
diff --git a/js/message_test.js b/js/message_test.js
index e038f65..3cac4c6 100644
--- a/js/message_test.js
+++ b/js/message_test.js
@@ -118,6 +118,8 @@
 goog.require('proto.jspb.test.TestExtensionsMessage');
 
 goog.require('proto.jspb.test.TestAllowAliasEnum');
+// CommonJS-LoadFromFile: testlargenumbers_pb proto.jspb.test
+goog.require('proto.jspb.test.MessageWithLargeFieldNumbers');
 
 describe('Message test suite', function() {
   var stubs = new goog.testing.PropertyReplacer();
@@ -1075,4 +1077,36 @@
     assertEquals(12, package2Message.getA());
   });
 
+
+  it('testMessageWithLargeFieldNumbers', function() {
+    var message = new proto.jspb.test.MessageWithLargeFieldNumbers;
+    
+    message.setAString('string');
+    assertEquals('string', message.getAString());
+
+    message.setAString('');
+    assertEquals('', message.getAString());
+
+    message.setAString('new string');
+    assertEquals('new string', message.getAString());
+
+    message.setABoolean(true);
+    assertEquals(true, message.getABoolean());
+
+    message.setABoolean(false);
+    assertEquals(false, message.getABoolean());
+
+    message.setABoolean(true);
+    assertEquals(true, message.getABoolean());
+
+    message.setAInt(42);
+    assertEquals(42, message.getAInt());
+
+    message.setAInt(0);
+    assertEquals(0, message.getAInt());
+
+    message.setAInt(42);
+    assertEquals(42, message.getAInt());
+  });
+
 });
diff --git a/js/package.json b/js/package.json
index a2fb371..14186be 100644
--- a/js/package.json
+++ b/js/package.json
@@ -1,6 +1,6 @@
 {
   "name": "google-protobuf",
-  "version": "3.11.2",
+  "version": "3.11.4",
   "description": "Protocol Buffers for JavaScript",
   "main": "google-protobuf.js",
   "files": [
diff --git a/js/testlargenumbers.proto b/js/testlargenumbers.proto
new file mode 100644
index 0000000..47aef35
--- /dev/null
+++ b/js/testlargenumbers.proto
@@ -0,0 +1,40 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package jspb.test;
+
+
+message MessageWithLargeFieldNumbers {
+  string a_string = 1;
+  bool a_boolean = 900;
+  int32 a_int = 5000;
+}
diff --git a/kokoro/linux/bazel/build.sh b/kokoro/linux/bazel/build.sh
index b5991d7..9355eba 100755
--- a/kokoro/linux/bazel/build.sh
+++ b/kokoro/linux/bazel/build.sh
@@ -25,9 +25,10 @@
 trap print_test_logs EXIT
 bazel test --copt=-Werror --host_copt=-Werror \
   //:build_files_updated_unittest \
+  //java/... \
   //:protobuf_test \
   @com_google_protobuf//:cc_proto_blacklist_test
 trap - EXIT
 
 cd examples
-bazel build :all
+bazel build //...
diff --git a/kokoro/linux/build_and_run_docker.sh b/kokoro/linux/build_and_run_docker.sh
index 3dc5dbb..cdbd6e2 100755
--- a/kokoro/linux/build_and_run_docker.sh
+++ b/kokoro/linux/build_and_run_docker.sh
@@ -28,8 +28,9 @@
   DOCKER_IMAGE_NAME=${DOCKERHUB_ORGANIZATION}/${DOCKERFILE_PREFIX}_$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ )
 fi
 
-# Pull dockerimage from Dockerhub
-docker pull $DOCKER_IMAGE_NAME
+# Pull dockerimage from Dockerhub. This sometimes fails intermittently, so we
+# keep trying until we succeed.
+until docker pull $DOCKER_IMAGE_NAME; do sleep 10; done
 
 # Ensure existence of ccache directory
 CCACHE_DIR=/tmp/protobuf-ccache
diff --git a/kokoro/linux/cpp_distcheck/build.sh b/kokoro/linux/cpp_distcheck/build.sh
index 1343a8c..42ac88c 100755
--- a/kokoro/linux/cpp_distcheck/build.sh
+++ b/kokoro/linux/cpp_distcheck/build.sh
@@ -11,7 +11,7 @@
 
 # Run tests under release docker image.
 DOCKER_IMAGE_NAME=protobuf/protoc_$(sha1sum protoc-artifacts/Dockerfile | cut -f1 -d " ")
-docker pull $DOCKER_IMAGE_NAME
+until docker pull $DOCKER_IMAGE_NAME; do sleep 10; done
 
 docker run -v $(pwd):/var/local/protobuf --rm $DOCKER_IMAGE_NAME \
   bash -l /var/local/protobuf/tests.sh cpp || FAILED="true"
diff --git a/kokoro/macos/php7.4_mac/build.sh b/kokoro/macos/php7.4_mac/build.sh
new file mode 100755
index 0000000..98c82d4
--- /dev/null
+++ b/kokoro/macos/php7.4_mac/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/macos/prepare_build_macos_rc
+
+./tests.sh php7.4_mac
diff --git a/kokoro/macos/php7.4_mac/continuous.cfg b/kokoro/macos/php7.4_mac/continuous.cfg
new file mode 100644
index 0000000..5b2d6fd
--- /dev/null
+++ b/kokoro/macos/php7.4_mac/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/php7.4_mac/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/php7.4_mac/presubmit.cfg b/kokoro/macos/php7.4_mac/presubmit.cfg
new file mode 100644
index 0000000..5b2d6fd
--- /dev/null
+++ b/kokoro/macos/php7.4_mac/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/php7.4_mac/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/prepare_build_macos_rc b/kokoro/macos/prepare_build_macos_rc
index 5b134f4..2428750 100755
--- a/kokoro/macos/prepare_build_macos_rc
+++ b/kokoro/macos/prepare_build_macos_rc
@@ -5,11 +5,11 @@
 ##
 # Select Xcode version
 
-# Remember to update the Xcode version when Xcode_11.0.app is not available.
+# Remember to update the Xcode version when Xcode_11.3.app is not available.
 # If xcode is not available, it will probably encounter the failure for
 # "autom4te: need GNU m4 1.4 or later: /usr/bin/m4"
 # go/kokoro/userdocs/macos/selecting_xcode.md for more information.
-export DEVELOPER_DIR=/Applications/Xcode_11.0.app/Contents/Developer
+export DEVELOPER_DIR=/Applications/Xcode_11.3.app/Contents/Developer
 
 ##
 # Select C/C++ compilers
diff --git a/kokoro/release/collect_all_artifacts.sh b/kokoro/release/collect_all_artifacts.sh
index 0023937..3b7d7d4 100755
--- a/kokoro/release/collect_all_artifacts.sh
+++ b/kokoro/release/collect_all_artifacts.sh
@@ -43,9 +43,7 @@
 cp ${INPUT_ARTIFACTS_DIR}/protoc-artifacts/target/linux/x86_32/protoc.exe protoc/linux_x86/protoc
 cp ${INPUT_ARTIFACTS_DIR}/protoc-artifacts/target/linux/x86_64/protoc.exe protoc/linux_x64/protoc
 
-mkdir -p protoc/macosx_x86
 mkdir -p protoc/macosx_x64
-cp ${INPUT_ARTIFACTS_DIR}/build32/src/protoc protoc/macosx_x86/protoc
 cp ${INPUT_ARTIFACTS_DIR}/build64/src/protoc protoc/macosx_x64/protoc
 
 # Install nuget (will also install  mono)
diff --git a/kokoro/release/protoc/macos/build.sh b/kokoro/release/protoc/macos/build.sh
index 6a4c79c..47c9bfa 100644
--- a/kokoro/release/protoc/macos/build.sh
+++ b/kokoro/release/protoc/macos/build.sh
@@ -6,14 +6,6 @@
 cd github/protobuf
 ./autogen.sh
 
-mkdir build32 && cd build32
-export CXXFLAGS="$CXXFLAGS_COMMON -m32"
-../configure --disable-shared
-make -j4
-file src/protoc
-otool -L src/protoc | grep dylib
-cd ..
-
 mkdir build64 && cd build64
 export CXXFLAGS="$CXXFLAGS_COMMON -m64"
 ../configure --disable-shared
diff --git a/php/ext/google/protobuf/def.c b/php/ext/google/protobuf/def.c
index 95085fc..5edcb03 100644
--- a/php/ext/google/protobuf/def.c
+++ b/php/ext/google/protobuf/def.c
@@ -132,6 +132,7 @@
 PHP_METHOD(Descriptor, getClass) {
   Descriptor* desc = UNBOX(Descriptor, getThis());
   DescriptorInternal* intern = desc->intern;
+  register_class(intern, false TSRMLS_CC);
 #if PHP_MAJOR_VERSION < 7
   const char* classname = intern->klass->name;
 #else
diff --git a/php/ext/google/protobuf/package.xml b/php/ext/google/protobuf/package.xml
index 99080b7..5cb2b46 100644
--- a/php/ext/google/protobuf/package.xml
+++ b/php/ext/google/protobuf/package.xml
@@ -10,11 +10,11 @@
   <email>protobuf-opensource@google.com</email>
   <active>yes</active>
  </lead>
- <date>2019-12-10</date>
- <time>11:22:54</time>
+ <date>2020-02-12</date>
+ <time>12:46:57</time>
  <version>
-  <release>3.11.2</release>
-  <api>3.11.2</api>
+  <release>3.11.4</release>
+  <api>3.11.4</api>
  </version>
  <stability>
   <release>stable</release>
@@ -501,5 +501,33 @@
    <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
    <notes>GA release.</notes>
   </release>
+  <release>
+   <version>
+    <release>3.11.3</release>
+    <api>3.11.3</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2020-01-28</date>
+   <time>10:20:43</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
+  <release>
+   <version>
+    <release>3.11.4</release>
+    <api>3.11.4</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2020-02-12</date>
+   <time>12:46:57</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>GA release.</notes>
+  </release>
  </changelog>
 </package>
diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h
index 4e6d56a..88cc400 100644
--- a/php/ext/google/protobuf/protobuf.h
+++ b/php/ext/google/protobuf/protobuf.h
@@ -37,7 +37,7 @@
 #include "upb.h"
 
 #define PHP_PROTOBUF_EXTNAME "protobuf"
-#define PHP_PROTOBUF_VERSION "3.11.2"
+#define PHP_PROTOBUF_VERSION "3.11.4"
 
 #define MAX_LENGTH_OF_INT64 20
 #define SIZEOF_INT64 8
@@ -292,7 +292,7 @@
 
 #define PHP_PROTO_HASH_OF(array) Z_ARRVAL_P(&array)
 
-static inline int php_proto_zend_hash_index_update_zval(HashTable* ht, ulong h,
+static inline int php_proto_zend_hash_index_update_zval(HashTable* ht, zend_ulong h,
                                                         zval* pData) {
   void* result = NULL;
   result = zend_hash_index_update(ht, h, pData);
@@ -308,7 +308,7 @@
   return result != NULL ? SUCCESS : FAILURE;
 }
 
-static inline int php_proto_zend_hash_index_update_mem(HashTable* ht, ulong h,
+static inline int php_proto_zend_hash_index_update_mem(HashTable* ht, zend_ulong h,
                                                    void* pData, uint nDataSize,
                                                    void** pDest) {
   void* result = NULL;
@@ -337,7 +337,7 @@
 }
 
 static inline int php_proto_zend_hash_index_find_zval(const HashTable* ht,
-                                                      ulong h, void** pDest) {
+                                                      zend_ulong h, void** pDest) {
   zval* result = zend_hash_index_find(ht, h);
   if (pDest != NULL) *pDest = result;
   return result != NULL ? SUCCESS : FAILURE;
@@ -351,7 +351,7 @@
 }
 
 static inline int php_proto_zend_hash_index_find_mem(const HashTable* ht,
-                                                     ulong h, void** pDest) {
+                                                     zend_ulong h, void** pDest) {
   void* result = NULL;
   result = zend_hash_index_find_ptr(ht, h);
   if (pDest != NULL) *pDest = result;
diff --git a/php/tests/descriptors_test.php b/php/tests/descriptors_test.php
index 93683b8..60a6292 100644
--- a/php/tests/descriptors_test.php
+++ b/php/tests/descriptors_test.php
@@ -11,6 +11,8 @@
 use Descriptors\TestDescriptorsEnum;
 use Descriptors\TestDescriptorsMessage;
 use Descriptors\TestDescriptorsMessage\Sub;
+use Foo\TestMessage;
+use Bar\TestInclude;
 
 class DescriptorsTest extends TestBase
 {
@@ -89,6 +91,17 @@
         $this->assertSame(1, $desc->getOneofDeclCount());
     }
 
+    public function testDescriptorForIncludedMessage()
+    {
+        $pool = DescriptorPool::getGeneratedPool();
+        $class = get_class(new TestMessage());
+        $this->assertSame('Foo\TestMessage', $class);
+        $desc = $pool->getDescriptorByClassName($class);
+        $fielddesc = $desc->getField(17);
+        $subdesc = $fielddesc->getMessageType();
+        $this->assertSame('Bar\TestInclude', $subdesc->getClass());
+    }
+
     #########################################################
     # Test enum descriptor.
     #########################################################
diff --git a/protobuf.bzl b/protobuf.bzl
index 5fa5543..26e84f5 100644
--- a/protobuf.bzl
+++ b/protobuf.bzl
@@ -318,29 +318,58 @@
         **kargs
     )
 
-def internal_gen_well_known_protos_java(srcs):
-    """Bazel rule to generate the gen_well_known_protos_java genrule
+def _internal_gen_well_known_protos_java_impl(ctx):
+    args = ctx.actions.args()
 
-    Args:
-      srcs: the well known protos
-    """
-    root = Label("%s//protobuf_java" % (native.repository_name())).workspace_root
-    pkg = native.package_name() + "/" if native.package_name() else ""
-    if root == "":
-        include = " -I%ssrc " % pkg
-    else:
-        include = " -I%s/%ssrc " % (root, pkg)
-    native.genrule(
-        name = "gen_well_known_protos_java",
-        srcs = srcs,
-        outs = [
-            "wellknown.srcjar",
-        ],
-        cmd = "$(location :protoc) --java_out=$(@D)/wellknown.jar" +
-              " %s $(SRCS) " % include +
-              " && mv $(@D)/wellknown.jar $(@D)/wellknown.srcjar",
-        tools = [":protoc"],
+    deps = [d[ProtoInfo] for d in ctx.attr.deps]
+
+    srcjar = ctx.actions.declare_file("{}.srcjar".format(ctx.attr.name))
+    args.add("--java_out", srcjar)
+
+    descriptors = depset(
+        transitive = [dep.transitive_descriptor_sets for dep in deps],
     )
+    args.add_joined(
+        "--descriptor_set_in",
+        descriptors,
+        join_with = ctx.configuration.host_path_separator,
+    )
+
+    for dep in deps:
+        if "." == dep.proto_source_root:
+            args.add_all([src.path for src in dep.direct_sources])
+        else:
+            source_root = dep.proto_source_root
+            offset = len(source_root) + 1  # + '/'.
+            args.add_all([src.path[offset:] for src in dep.direct_sources])
+
+    ctx.actions.run(
+        executable = ctx.executable._protoc,
+        inputs = descriptors,
+        outputs = [srcjar],
+        arguments = [args],
+    )
+
+    return [
+        DefaultInfo(
+            files = depset([srcjar]),
+        ),
+    ]
+
+internal_gen_well_known_protos_java = rule(
+    implementation = _internal_gen_well_known_protos_java_impl,
+    attrs = {
+        "deps": attr.label_list(
+            mandatory = True,
+            providers = [ProtoInfo],
+        ),
+        "_protoc": attr.label(
+            executable = True,
+            cfg = "host",
+            default = "@com_google_protobuf//:protoc",
+        ),
+    },
+)
 
 def internal_copied_filegroup(name, srcs, strip_prefix, dest, **kwargs):
     """Macro to copy files to a different directory and then create a filegroup.
diff --git a/protoc-artifacts/build-zip.sh b/protoc-artifacts/build-zip.sh
index 9921c2d..2a25d3c 100755
--- a/protoc-artifacts/build-zip.sh
+++ b/protoc-artifacts/build-zip.sh
@@ -13,10 +13,9 @@
 This script will download pre-built protoc or protoc plugin binaries from maven
 repository and create .zip packages suitable to be included in the github
 release page. If the target is protoc, well-known type .proto files will also be
-included. Each invocation will create 9 zip packages:
+included. Each invocation will create 8 zip packages:
   dist/<TARGET>-<VERSION_NUMBER>-win32.zip
   dist/<TARGET>-<VERSION_NUMBER>-win64.zip
-  dist/<TARGET>-<VERSION_NUMBER>-osx-x86_32.zip
   dist/<TARGET>-<VERSION_NUMBER>-osx-x86_64.zip
   dist/<TARGET>-<VERSION_NUMBER>-linux-x86_32.zip
   dist/<TARGET>-<VERSION_NUMBER>-linux-x86_64.zip
@@ -34,7 +33,6 @@
 declare -a FILE_NAMES=( \
   win32.zip windows-x86_32.exe \
   win64.zip windows-x86_64.exe \
-  osx-x86_32.zip osx-x86_32.exe \
   osx-x86_64.zip osx-x86_64.exe \
   linux-x86_32.zip linux-x86_32.exe \
   linux-x86_64.zip linux-x86_64.exe \
@@ -100,7 +98,7 @@
     BINARY="$TARGET"
   fi
   BINARY_NAME=${FILE_NAMES[$(($i+1))]}
-  BINARY_URL=http://repo1.maven.org/maven2/com/google/protobuf/$TARGET/${VERSION_NUMBER}/$TARGET-${VERSION_NUMBER}-${BINARY_NAME}
+  BINARY_URL=https://repo1.maven.org/maven2/com/google/protobuf/$TARGET/${VERSION_NUMBER}/$TARGET-${VERSION_NUMBER}-${BINARY_NAME}
   if ! wget ${BINARY_URL} -O ${DIR}/bin/$BINARY &> /dev/null; then
     echo "[ERROR] Failed to download ${BINARY_URL}" >&2
     echo "[ERROR] Skipped $TARGET-${VERSION_NAME}-${ZIP_NAME}" >&2
diff --git a/protoc-artifacts/pom.xml b/protoc-artifacts/pom.xml
index 80d282d..327e3d7 100644
--- a/protoc-artifacts/pom.xml
+++ b/protoc-artifacts/pom.xml
@@ -8,7 +8,7 @@
   </parent>
   <groupId>com.google.protobuf</groupId>
   <artifactId>protoc</artifactId>
-  <version>3.11.2</version>
+  <version>3.11.4</version>
   <packaging>pom</packaging>
   <name>Protobuf Compiler</name>
   <description>
@@ -71,11 +71,6 @@
                   <type>exe</type>
                 </artifact>
                 <artifact>
-                  <file>${basedir}/target/osx/x86_32/protoc.exe</file>
-                  <classifier>osx-x86_32</classifier>
-                  <type>exe</type>
-                </artifact>
-                <artifact>
                   <file>${basedir}/target/linux/aarch_64/protoc.exe</file>
                   <classifier>linux-aarch_64</classifier>
                   <type>exe</type>
diff --git a/python/google/protobuf/__init__.py b/python/google/protobuf/__init__.py
index 25d2445..cc9a06a 100755
--- a/python/google/protobuf/__init__.py
+++ b/python/google/protobuf/__init__.py
@@ -30,7 +30,7 @@
 
 # Copyright 2007 Google Inc. All Rights Reserved.
 
-__version__ = '3.11.2'
+__version__ = '3.11.4'
 
 if __name__ != '__main__':
   try:
diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c
index 22e3efb..142fd57 100644
--- a/ruby/ext/google/protobuf_c/encode_decode.c
+++ b/ruby/ext/google/protobuf_c/encode_decode.c
@@ -1466,6 +1466,7 @@
   MessageHeader* msg;
   upb_msg_field_iter i;
   upb_status status;
+  bool json_wrapper = is_wrapper(desc->msgdef) && is_json;
 
   if (is_json &&
       upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_ANY) {
@@ -1542,7 +1543,7 @@
         is_default = RSTRING_LEN(str) == 0;
       }
 
-      if (is_matching_oneof || emit_defaults || !is_default) {
+      if (is_matching_oneof || emit_defaults || !is_default || json_wrapper) {
         putstr(str, f, sink);
       }
     } else if (upb_fielddef_issubmsg(f)) {
@@ -1562,7 +1563,7 @@
     } else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) {       \
       is_default = default_value == value;                                   \
     }                                                                        \
-    if (is_matching_oneof || emit_defaults || !is_default) {                 \
+    if (is_matching_oneof || emit_defaults || !is_default || json_wrapper) { \
       upb_sink_put##upbtype(sink, sel, value);                               \
     }                                                                        \
   } break;
diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec
index ba7acbc..bf60b6a 100644
--- a/ruby/google-protobuf.gemspec
+++ b/ruby/google-protobuf.gemspec
@@ -1,6 +1,6 @@
 Gem::Specification.new do |s|
   s.name        = "google-protobuf"
-  s.version     = "3.11.2"
+  s.version     = "3.11.4"
   git_tag       = "v#{s.version.to_s.sub('.rc.', '-rc')}" # Converts X.Y.Z.rc.N to vX.Y.Z-rcN, used for the git tag
   s.licenses    = ["BSD-3-Clause"]
   s.summary     = "Protocol Buffers"
diff --git a/ruby/tests/common_tests.rb b/ruby/tests/common_tests.rb
index ee05b85..7414aea 100644
--- a/ruby/tests/common_tests.rb
+++ b/ruby/tests/common_tests.rb
@@ -1293,6 +1293,7 @@
     run_asserts.call(m)
     m2 = proto_module::Wrapper.decode(m.to_proto)
     run_asserts.call(m2)
+    m3 = proto_module::Wrapper.decode_json(m.to_json)
   end
 
   def test_wrapper_getters
diff --git a/src/Makefile.am b/src/Makefile.am
index 5ac489b..7d5e779 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,7 +18,7 @@
 PTHREAD_DEF =
 endif
 
-PROTOBUF_VERSION = 22:2:0
+PROTOBUF_VERSION = 22:4:0
 
 if GCC
 # Turn on all warnings except for sign comparison (we ignore sign comparison
diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h
index f551818..0ff9341 100644
--- a/src/google/protobuf/any.pb.h
+++ b/src/google/protobuf/any.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h
index b00b88d..ed49df1 100644
--- a/src/google/protobuf/api.pb.h
+++ b/src/google/protobuf/api.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index d73b53c..2dcf817 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -248,7 +248,7 @@
 // well as protobuf container types like RepeatedPtrField and Map. The protocol
 // is internal to protobuf and is not guaranteed to be stable. Non-proto types
 // should not rely on this protocol.
-class PROTOBUF_EXPORT alignas(8) Arena final {
+class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
  public:
   // Arena constructor taking custom options. See ArenaOptions below for
   // descriptions of the options available.
@@ -338,8 +338,10 @@
   template <typename T>
   PROTOBUF_ALWAYS_INLINE static T* CreateArray(Arena* arena,
                                                size_t num_elements) {
+#ifndef __INTEL_COMPILER // icc mis-evaluates some types as non-pod
     static_assert(std::is_pod<T>::value,
                   "CreateArray requires a trivially constructible type");
+#endif
     static_assert(std::is_trivially_destructible<T>::value,
                   "CreateArray requires a trivially destructible type");
     GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index c5b2030..fd64d0f 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -886,7 +886,8 @@
     for (int i = 0; i < output_directives_.size(); i++) {
       std::string output_location = output_directives_[i].output_location;
       if (!HasSuffixString(output_location, ".zip") &&
-          !HasSuffixString(output_location, ".jar")) {
+          !HasSuffixString(output_location, ".jar") &&
+          !HasSuffixString(output_location, ".srcjar")) {
         AddTrailingSlash(&output_location);
       }
 
@@ -2228,12 +2229,20 @@
   }
 
   io::FileOutputStream out(fd);
-  if (!file_set.SerializeToZeroCopyStream(&out)) {
-    std::cerr << descriptor_set_out_name_ << ": " << strerror(out.GetErrno())
-              << std::endl;
-    out.Close();
-    return false;
+
+  {
+    io::CodedOutputStream coded_out(&out);
+    // Determinism is useful here because build outputs are sometimes checked
+    // into version control.
+    coded_out.SetSerializationDeterministic(true);
+    if (!file_set.SerializeToCodedStream(&coded_out)) {
+      std::cerr << descriptor_set_out_name_ << ": " << strerror(out.GetErrno())
+                << std::endl;
+      out.Close();
+      return false;
+    }
   }
+
   if (!out.Close()) {
     std::cerr << descriptor_set_out_name_ << ": " << strerror(out.GetErrno())
               << std::endl;
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index 0fdf8c6..6061e3c 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 30e85cc..e7bae0d 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
diff --git a/src/google/protobuf/duration.pb.h b/src/google/protobuf/duration.pb.h
index 7b34a4b..b2efc3c 100644
--- a/src/google/protobuf/duration.pb.h
+++ b/src/google/protobuf/duration.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
diff --git a/src/google/protobuf/empty.pb.h b/src/google/protobuf/empty.pb.h
index 66312bc..7d24d89 100644
--- a/src/google/protobuf/empty.pb.h
+++ b/src/google/protobuf/empty.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h
index f3f8319..af6b8a9 100644
--- a/src/google/protobuf/field_mask.pb.h
+++ b/src/google/protobuf/field_mask.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index 3bd6263..0b393fb 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -1193,11 +1193,11 @@
   const Message* unused = static_cast<T*>(nullptr);
   (void)unused;
 
-#ifdef GOOGLE_PROTOBUF_NO_RTTI
+#if PROTOBUF_RTTI
+  return dynamic_cast<const T*>(from);
+#else
   bool ok = T::default_instance().GetReflection() == from->GetReflection();
   return ok ? down_cast<const T*>(from) : nullptr;
-#else
-  return dynamic_cast<const T*>(from);
 #endif
 }
 
diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc
index 3e39f91..d09877b 100644
--- a/src/google/protobuf/port_def.inc
+++ b/src/google/protobuf/port_def.inc
@@ -297,7 +297,7 @@
 
 // Shared google3/opensource definitions. //////////////////////////////////////
 
-#define PROTOBUF_VERSION 3011002
+#define PROTOBUF_VERSION 3011004
 #define PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC 3011000
 #define PROTOBUF_MIN_PROTOC_VERSION 3011000
 #define PROTOBUF_VERSION_SUFFIX ""
@@ -382,6 +382,8 @@
 // Windows declares several inconvenient macro names.  We #undef them and then
 // restore them in port_undef.inc.
 #ifdef _MSC_VER
+#pragma push_macro("ERROR")
+#undef ERROR
 #pragma push_macro("GetMessage")
 #undef GetMessage
 #pragma push_macro("IGNORE")
@@ -420,3 +422,32 @@
 #else
 #define PROTOBUF_ASSUME(pred) GOOGLE_DCHECK(pred)
 #endif
+
+// Specify memory alignment for structs, classes, etc.
+// Use like:
+//   class PROTOBUF_ALIGNAS(16) MyClass { ... }
+//   PROTOBUF_ALIGNAS(16) int array[4];
+//
+// In most places you can use the C++11 keyword "alignas", which is preferred.
+//
+// But compilers have trouble mixing __attribute__((...)) syntax with
+// alignas(...) syntax.
+//
+// Doesn't work in clang or gcc:
+//   struct alignas(16) __attribute__((packed)) S { char c; };
+// Works in clang but not gcc:
+//   struct __attribute__((packed)) alignas(16) S2 { char c; };
+// Works in clang and gcc:
+//   struct alignas(16) S3 { char c; } __attribute__((packed));
+//
+// There are also some attributes that must be specified *before* a class
+// definition: visibility (used for exporting functions/classes) is one of
+// these attributes. This means that it is not possible to use alignas() with a
+// class that is marked as exported.
+#if defined(_MSC_VER)
+#define PROTOBUF_ALIGNAS(byte_alignment) __declspec(align(byte_alignment))
+#elif defined(__GNUC__)
+#define PROTOBUF_ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
+#else
+#define PROTOBUF_ALIGNAS(byte_alignment) alignas(byte_alignment)
+#endif
diff --git a/src/google/protobuf/port_undef.inc b/src/google/protobuf/port_undef.inc
index 80822b4..2cc56f3 100644
--- a/src/google/protobuf/port_undef.inc
+++ b/src/google/protobuf/port_undef.inc
@@ -68,9 +68,11 @@
 #undef PROTOBUF_ASSUME
 #undef PROTOBUF_EXPORT_TEMPLATE_DECLARE
 #undef PROTOBUF_EXPORT_TEMPLATE_DEFINE
+#undef PROTOBUF_ALIGNAS
 
 // Restore macro that may have been #undef'd in port_def.inc.
 #ifdef _MSC_VER
+#pragma pop_macro("ERROR")
 #pragma pop_macro("GetMessage")
 #pragma pop_macro("IGNORE")
 #pragma pop_macro("IN")
diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h
index c9c70c8..2861a69 100644
--- a/src/google/protobuf/source_context.pb.h
+++ b/src/google/protobuf/source_context.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h
index 9d2ccb2..46363e4 100644
--- a/src/google/protobuf/struct.pb.h
+++ b/src/google/protobuf/struct.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
diff --git a/src/google/protobuf/stubs/casts.h b/src/google/protobuf/stubs/casts.h
index b509f68..780857b 100644
--- a/src/google/protobuf/stubs/casts.h
+++ b/src/google/protobuf/stubs/casts.h
@@ -35,9 +35,12 @@
 
 #include <google/protobuf/stubs/common.h>
 
+#include <google/protobuf/port_def.inc>
+
 namespace google {
 namespace protobuf {
 namespace internal {
+
 // Use implicit_cast as a safe version of static_cast or const_cast
 // for upcasting in the type hierarchy (i.e. casting a pointer to Foo
 // to a pointer to SuperclassOfFoo or casting a pointer to Foo to
@@ -88,7 +91,7 @@
     implicit_cast<From*, To>(0);
   }
 
-#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
+#if !defined(NDEBUG) && PROTOBUF_RTTI
   assert(f == nullptr || dynamic_cast<To>(f) != nullptr);  // RTTI: debug mode only!
 #endif
   return static_cast<To>(f);
@@ -105,7 +108,7 @@
     implicit_cast<From*, ToAsPointer>(0);
   }
 
-#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
+#if !defined(NDEBUG) && PROTOBUF_RTTI
   // RTTI: debug mode only!
   assert(dynamic_cast<ToAsPointer>(&f) != nullptr);
 #endif
@@ -131,4 +134,7 @@
 
 }  // namespace protobuf
 }  // namespace google
+
+#include <google/protobuf/port_undef.inc>
+
 #endif  // GOOGLE_PROTOBUF_CASTS_H__
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index ef7ace9..1c9084f 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -81,7 +81,7 @@
 
 // The current version, represented as a single integer to make comparison
 // easier:  major * 10^6 + minor * 10^3 + micro
-#define GOOGLE_PROTOBUF_VERSION 3011002
+#define GOOGLE_PROTOBUF_VERSION 3011004
 
 // A suffix string for alpha, beta or rc releases. Empty for stable releases.
 #define GOOGLE_PROTOBUF_VERSION_SUFFIX ""
diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
index e688c8e..f319bfc 100644
--- a/src/google/protobuf/stubs/strutil.h
+++ b/src/google/protobuf/stubs/strutil.h
@@ -35,6 +35,7 @@
 
 #include <stdlib.h>
 #include <vector>
+#include <cstring>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/stringpiece.h>
 
@@ -117,6 +118,12 @@
   return str.size() >= prefix.size() &&
          str.compare(0, prefix.size(), prefix) == 0;
 }
+  
+inline bool HasPrefixString(StringPiece str,
+                            StringPiece prefix) {
+  return str.size() >= prefix.size() &&
+  		 memcmp(str.data(), prefix.data(), prefix.size()) == 0;
+}
 
 inline string StripPrefixString(const string& str, const string& prefix) {
   if (HasPrefixString(str, prefix)) {
diff --git a/src/google/protobuf/timestamp.pb.h b/src/google/protobuf/timestamp.pb.h
index 338a1e7..f0a4330 100644
--- a/src/google/protobuf/timestamp.pb.h
+++ b/src/google/protobuf/timestamp.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h
index 40d2cd4..8756c93 100644
--- a/src/google/protobuf/type.pb.h
+++ b/src/google/protobuf/type.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h
index ebde03a..dd03416 100644
--- a/src/google/protobuf/wrappers.pb.h
+++ b/src/google/protobuf/wrappers.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3011002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
diff --git a/tests.sh b/tests.sh
index 9e72cb5..bda7e53 100755
--- a/tests.sh
+++ b/tests.sh
@@ -705,6 +705,30 @@
   popd
 }
 
+build_php7.4_mac() {
+  generate_php_test_proto
+  # Install PHP
+  curl -s https://php-osx.liip.ch/install.sh | bash -s 7.4
+  PHP_FOLDER=`find /usr/local -type d -name "php7-7.4*"`  # The folder name may change upon time
+  export PATH="$PHP_FOLDER/bin:$PATH"
+
+  # Install phpunit
+  curl https://phar.phpunit.de/phpunit-8.phar -L -o phpunit.phar
+  chmod +x phpunit.phar
+  sudo mv phpunit.phar /usr/local/bin/phpunit
+
+  # Install valgrind
+  echo "#! /bin/bash" > valgrind
+  chmod ug+x valgrind
+  sudo mv valgrind /usr/local/bin/valgrind
+
+  # Test
+  cd php/tests && /bin/bash ./test.sh && cd ../..
+  pushd conformance
+  make test_php_c
+  popd
+}
+
 build_php_compatibility() {
   internal_build_cpp
   php/tests/compatibility_test.sh $LAST_RELEASED