diff --git a/packages/bundle-size/README.md b/packages/bundle-size/README.md
index 819170e1b..5d4099fbb 100644
--- a/packages/bundle-size/README.md
+++ b/packages/bundle-size/README.md
@@ -15,11 +15,11 @@ usually do. We repeat this for an increasing number of files.
| code generator | files | bundle size | minified | compressed |
|-----------------|----------|------------------------:|-----------------------:|-------------------:|
-| protobuf-es | 1 | 79,466 b | 34,303 b | 9,800 b |
-| protobuf-es | 4 | 92,563 b | 37,277 b | 10,113 b |
-| protobuf-es | 8 | 101,904 b | 41,775 b | 10,824 b |
-| protobuf-es | 16 | 165,584 b | 67,020 b | 13,312 b |
-| protobuf-es | 32 | 344,962 b | 147,972 b | 20,177 b |
+| protobuf-es | 1 | 79,463 b | 34,300 b | 9,781 b |
+| protobuf-es | 4 | 92,560 b | 37,274 b | 10,114 b |
+| protobuf-es | 8 | 101,901 b | 41,772 b | 10,808 b |
+| protobuf-es | 16 | 165,581 b | 67,017 b | 13,320 b |
+| protobuf-es | 32 | 344,959 b | 147,969 b | 20,175 b |
| protobuf-javascript | 1 | 339,613 b | 255,820 b | 42,481 b |
| protobuf-javascript | 4 | 366,281 b | 271,092 b | 43,912 b |
| protobuf-javascript | 8 | 388,324 b | 283,409 b | 45,038 b |
diff --git a/packages/bundle-size/chart.svg b/packages/bundle-size/chart.svg
index 57e6de001..e38dc5bbf 100644
--- a/packages/bundle-size/chart.svg
+++ b/packages/bundle-size/chart.svg
@@ -43,14 +43,14 @@
0 KiB
-
+
protobuf-es
-protobuf-es 9.57 KiB for 1 files
-protobuf-es 9.88 KiB for 4 files
-protobuf-es 10.57 KiB for 8 files
-protobuf-es 13 KiB for 16 files
-protobuf-es 19.7 KiB for 32 files
+protobuf-es 9.55 KiB for 1 files
+protobuf-es 9.88 KiB for 4 files
+protobuf-es 10.55 KiB for 8 files
+protobuf-es 13.01 KiB for 16 files
+protobuf-es 19.7 KiB for 32 files
diff --git a/packages/protobuf-test/src/constructor.test.ts b/packages/protobuf-test/src/constructor.test.ts
index 6db23360a..e241e6092 100644
--- a/packages/protobuf-test/src/constructor.test.ts
+++ b/packages/protobuf-test/src/constructor.test.ts
@@ -21,6 +21,8 @@ import { TestAllTypesProto3 as JS_TestAllTypesProto3 } from "./gen/js/google/pro
import { JSTypeStringMessage as TS_JSTypeStringMessage } from "./gen/ts/extra/jstype_pb.js";
import { JSTypeStringMessage as JS_JSTypeStringMessage } from "./gen/js/extra/jstype_pb.js";
import { testMT } from "./helpers.js";
+import { Proto3OptionalMessage as TS_Proto3OptionalMessage } from "./gen/ts/extra/proto3_pb.js";
+import { Proto3OptionalMessage as JS_Proto3OptionalMessage } from "./gen/js/extra/proto3_pb.js";
describe("constructor initializes jstype=JS_STRING with string", function () {
testMT(
@@ -179,3 +181,47 @@ describe("constructor takes partial message for map value", function () {
},
);
});
+
+describe("constructor skips undefined values", () => {
+ testMT(
+ { ts: TS_Proto3OptionalMessage, js: JS_Proto3OptionalMessage },
+ (messageType) => {
+ const m = new messageType({
+ stringField: undefined,
+ });
+ expect(m.stringField).toBeUndefined();
+ },
+ );
+ testMT(
+ { ts: TS_TestAllTypesProto3, js: JS_TestAllTypesProto3 },
+ (messageType) => {
+ const m = new messageType({
+ optionalInt32: undefined,
+ });
+ expect(m.optionalInt32).toBe(0);
+ },
+ );
+});
+
+describe("constructor skips null values", () => {
+ testMT(
+ { ts: TS_Proto3OptionalMessage, js: JS_Proto3OptionalMessage },
+ (messageType) => {
+ const m = new messageType({
+ // @ts-expect-error TS 2322
+ stringField: null,
+ });
+ expect(m.stringField).toBeUndefined();
+ },
+ );
+ testMT(
+ { ts: TS_TestAllTypesProto3, js: JS_TestAllTypesProto3 },
+ (messageType) => {
+ const m = new messageType({
+ // @ts-expect-error TS 2322
+ optionalInt32: null,
+ });
+ expect(m.optionalInt32).toBe(0);
+ },
+ );
+});
diff --git a/packages/protobuf/src/private/util-common.ts b/packages/protobuf/src/private/util-common.ts
index 42f4e6340..c03bc5d00 100644
--- a/packages/protobuf/src/private/util-common.ts
+++ b/packages/protobuf/src/private/util-common.ts
@@ -38,7 +38,7 @@ export function makeUtilCommon(): Omit {
const localName = member.localName,
t = target as AnyMessage,
s = source as PartialMessage;
- if (s[localName] === undefined) {
+ if (s[localName] == null) {
// TODO if source is a Message instance, we should use isFieldSet() here to support future field presence
continue;
}