From eeb911a5bf73c5100eebeaa89929bdd434ef8e4b Mon Sep 17 00:00:00 2001 From: Timo Stamm Date: Wed, 31 Jan 2024 20:02:58 +0100 Subject: [PATCH] Fix proto3 extension presence for singular, non-optional scalar (#689) --- packages/protobuf-bench/README.md | 2 +- packages/protobuf-test/src/extensions-proto3.test.ts | 5 +++-- packages/protobuf/src/extension-accessor.ts | 9 ++++++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/protobuf-bench/README.md b/packages/protobuf-bench/README.md index 9e4f42003..a779e08bd 100644 --- a/packages/protobuf-bench/README.md +++ b/packages/protobuf-bench/README.md @@ -10,5 +10,5 @@ server would usually do. | code generator | bundle size | minified | compressed | |---------------------|------------------------:|-----------------------:|-------------------:| -| protobuf-es | 96,275 b | 41,035 b | 10,663 b | +| protobuf-es | 96,441 b | 41,150 b | 10,720 b | | protobuf-javascript | 394,384 b | 288,654 b | 45,122 b | diff --git a/packages/protobuf-test/src/extensions-proto3.test.ts b/packages/protobuf-test/src/extensions-proto3.test.ts index 82ad1af26..957af7a3e 100644 --- a/packages/protobuf-test/src/extensions-proto3.test.ts +++ b/packages/protobuf-test/src/extensions-proto3.test.ts @@ -55,10 +55,11 @@ describe("setExtension() proto3", () => { expect(hasExtension(msg, ext)).toBeTruthy(); expect(getExtension(msg, ext)).toStrictEqual(123); }); - it("should not set zero value", () => { + it("should set zero value, even without optional keyword", () => { + // Implicit presence does not apply to extensions, see https://github.com/protocolbuffers/protobuf/issues/8234 const msg = new FileOptions(); setExtension(msg, ext, 0); - expect(hasExtension(msg, ext)).toBeFalsy(); + expect(hasExtension(msg, ext)).toBeTruthy(); expect(getExtension(msg, ext)).toStrictEqual(0); }); }); diff --git a/packages/protobuf/src/extension-accessor.ts b/packages/protobuf/src/extension-accessor.ts index f55fa51ee..f45debc4d 100644 --- a/packages/protobuf/src/extension-accessor.ts +++ b/packages/protobuf/src/extension-accessor.ts @@ -20,6 +20,7 @@ import { filterUnknownFields, } from "./private/extensions.js"; import type { Extension } from "./extension.js"; +import type { FieldInfo } from "./field.js"; /** * Retrieve an extension value from a message. @@ -87,7 +88,13 @@ export function setExtension, V>( } } const writer = writeOpt.writerFactory(); - extension.runtime.bin.writeField(extension.field, value, writer, writeOpt); + let f: FieldInfo = extension.field; + // Implicit presence does not apply to extensions, see https://github.com/protocolbuffers/protobuf/issues/8234 + // We patch the field info to use explicit presence: + if (!f.opt && !f.repeated && (f.kind == "enum" || f.kind == "scalar")) { + f = { ...extension.field, opt: true } as FieldInfo; + } + extension.runtime.bin.writeField(f, value, writer, writeOpt); const reader = readOpt.readerFactory(writer.finish()); while (reader.pos < reader.len) { const [no, wireType] = reader.tag();