Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update dependency protobufjs to v7.4.0 #19

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

renovate[bot]
Copy link
Contributor

@renovate renovate bot commented Jan 29, 2025

This PR contains the following updates:

Package Change Age Adoption Passing Confidence
protobufjs (source) 7.2.5 -> 7.4.0 age adoption passing confidence

Release Notes

protobufjs/protobuf.js (protobufjs)

v7.4.0

Compare Source

Features
  • Add prepublishOnly script (0e4da8b)
Bug Fixes

v7.3.3

Compare Source

Bug Fixes
  • handle nullability for optional fields (59569c1)

v7.3.2

Compare Source

Bug Fixes
  • docs: Update readme to correct command for creating types (#​1939) (0f9d477)

v7.3.1

Compare Source

Bug Fixes
  • types: reserved field in IType can contain reserved names (#​2001) (d1d2c0c)

v7.3.0

Compare Source

Features

v7.2.6

Compare Source

Bug Fixes

Configuration

📅 Schedule: Branch creation - "* 0-4 * * 3" (UTC), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

Copy link

[puLL-Merge] - protobufjs/[email protected]

Diff
diff --git .release-please-manifest.json .release-please-manifest.json
index 01d761f46..14a9bf896 100644
--- .release-please-manifest.json
+++ .release-please-manifest.json
@@ -1 +1 @@
-{".":"7.2.5","cli":"1.1.2"}
+{".":"7.4.0","cli":"1.1.4"}
diff --git CHANGELOG.md CHANGELOG.md
index de681cb72..23a0f2088 100644
--- CHANGELOG.md
+++ CHANGELOG.md
@@ -1,5 +1,52 @@
 # Changelog
 
+## [7.4.0](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.3.3...protobufjs-v7.4.0) (2024-08-22)
+
+
+### Features
+
+* Add `prepublishOnly` script ([0e4da8b](https://github.com/protobufjs/protobuf.js/commit/0e4da8b158a85af5160e2f4ba5eb097a8dc65cb1))
+
+
+### Bug Fixes
+
+* include ([28e3334](https://github.com/protobufjs/protobuf.js/commit/28e333415d3c85687810e164125997d17baba0bd))
+
+## [7.3.3](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.3.2...protobufjs-v7.3.3) (2024-08-16)
+
+
+### Bug Fixes
+
+* handle nullability for optional fields ([59569c1](https://github.com/protobufjs/protobuf.js/commit/59569c12c85c1c7b783ace9a71775b1d05a08e9c))
+
+## [7.3.2](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.3.1...protobufjs-v7.3.2) (2024-06-12)
+
+
+### Bug Fixes
+
+* **docs:** Update readme to correct command for creating types ([#1939](https://github.com/protobufjs/protobuf.js/issues/1939)) ([0f9d477](https://github.com/protobufjs/protobuf.js/commit/0f9d4770e0fb360c767241a13696d73edc6536b7))
+
+## [7.3.1](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.3.0...protobufjs-v7.3.1) (2024-06-05)
+
+
+### Bug Fixes
+
+* **types:** reserved field in IType can contain reserved names ([#2001](https://github.com/protobufjs/protobuf.js/issues/2001)) ([d1d2c0c](https://github.com/protobufjs/protobuf.js/commit/d1d2c0c7890e07ca1302c83a136051ee0624cba8))
+
+## [7.3.0](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.2.6...protobufjs-v7.3.0) (2024-05-10)
+
+
+### Features
+
+* add handling for extension range options ([#1990](https://github.com/protobufjs/protobuf.js/issues/1990)) ([2d58011](https://github.com/protobufjs/protobuf.js/commit/2d58011cc0bc495c68ed70f5aad297deb1722378))
+
+## [7.2.6](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.2.5...protobufjs-v7.2.6) (2024-01-16)
+
+
+### Bug Fixes
+
+* report missing import properly in loadSync ([#1960](https://github.com/protobufjs/protobuf.js/issues/1960)) ([af3ff83](https://github.com/protobufjs/protobuf.js/commit/af3ff83dc41c7736b7e57f2a02fd94ac03b76a4c))
+
 ## [7.2.5](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.2.4...protobufjs-v7.2.5) (2023-08-21)
 
 
diff --git README.md README.md
index b88c0229f..46752a93d 100644
--- README.md
+++ README.md
@@ -1,9 +1,15 @@
-<h1><p align="center"><img alt="protobuf.js" src="https://github.com/dcodeIO/protobuf.js/raw/master/pbjs.png" width="120" height="104" /></p></h1>
-<p align="center"><a href="https://npmjs.org/package/protobufjs"><img src="https://img.shields.io/npm/v/protobufjs.svg" alt=""></a> <a href="https://travis-ci.org/dcodeIO/protobuf.js"><img src="https://travis-ci.org/dcodeIO/protobuf.js.svg?branch=master" alt=""></a> <a href="https://npmjs.org/package/protobufjs"><img src="https://img.shields.io/npm/dm/protobufjs.svg" alt=""></a> <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=dcode%40dcode.io&item_name=Open%20Source%20Software%20Donation&item_number=dcodeIO%2Fprotobuf.js"><img alt="donate ❤" src="https://img.shields.io/badge/donate-❤-ff2244.svg"></a></p>
+<h1><p align="center"><img alt="protobuf.js" src="https://github.com/protobufjs/protobuf.js/raw/master/pbjs.svg" height="100" /><br/>protobuf.js</p></h1>
+<p align="center">
+  <a href="https://github.com/protobufjs/protobuf.js/actions/workflows/test.yml"><img src="https://img.shields.io/github/actions/workflow/status/protobufjs/protobuf.js/test.yml?branch=master&label=build&logo=github" alt=""></a>
+  <a href="https://github.com/protobufjs/protobuf.js/actions/workflows/release.yaml"><img src="https://img.shields.io/github/actions/workflow/status/protobufjs/protobuf.js/release.yaml?branch=master&label=release&logo=github" alt=""></a>
+  <a href="https://npmjs.org/package/protobufjs"><img src="https://img.shields.io/npm/v/protobufjs.svg?logo=npm" alt=""></a>
+  <a href="https://npmjs.org/package/protobufjs"><img src="https://img.shields.io/npm/dm/protobufjs.svg?label=downloads&logo=npm" alt=""></a>
+  <a href="https://www.jsdelivr.com/package/npm/protobufjs"><img src="https://img.shields.io/jsdelivr/npm/hm/protobufjs?label=requests&logo=jsdelivr" alt=""></a>
+</p>
 
-**Protocol Buffers** are a language-neutral, platform-neutral, extensible way of serializing structured data for use in communications protocols, data storage, and more, originally designed at Google ([see](https://developers.google.com/protocol-buffers/)).
+**Protocol Buffers** are a language-neutral, platform-neutral, extensible way of serializing structured data for use in communications protocols, data storage, and more, originally designed at Google ([see](https://protobuf.dev/)).
 
-**protobuf.js** is a pure JavaScript implementation with [TypeScript](https://www.typescriptlang.org) support for [node.js](https://nodejs.org) and the browser. It's easy to use, blazingly fast and works out of the box with [.proto](https://developers.google.com/protocol-buffers/docs/proto) files!
+**protobuf.js** is a pure JavaScript implementation with [TypeScript](https://www.typescriptlang.org) support for [Node.js](https://nodejs.org) and the browser. It's easy to use, does not sacrifice on performance, has good conformance and works out of the box with [.proto](https://protobuf.dev/programming-guides/proto3/) files!
 
 Contents
 --------
@@ -42,68 +48,49 @@ Contents
 Installation
 ---------------
 
-### node.js
+### Node.js
 
-\`\`\`
-$> npm install protobufjs [--save --save-prefix=~]
+```sh
+npm install protobufjs --save
+// Static code + Reflection + .proto parser
var protobuf = require("protobufjs");
-```

-The command line utility lives in the protobufjs-cli package and must be installed separately:
+// Static code + Reflection
+var protobuf = require("protobufjs/light");

+// Static code only
+var protobuf = require("protobufjs/minimal");

-$> npm install protobufjs-cli [--save --save-prefix=~]
-```

-Note that this library's versioning scheme is not semver-compatible for historical reasons. For guaranteed backward compatibility, always depend on ~6.A.B instead of ^6.A.B (hence the --save-prefix above).

-### Browsers

-Development:
+The optional command line utility to generate static code and reflection bundles lives in the protobufjs-cli package and can be installed separately:

- -<script src="//cdn.jsdelivr.net/npm/[email protected]/dist/protobuf.js"></script> +sh
+npm install protobufjs-cli --save-dev


-Production:
+### Browsers

-```
+Pick the variant matching your needs and replace the version tag with the exact [release](https://github.com/protobufjs/protobuf.js/tags) your project depends upon. For example, to use the minified full variant:
+
+```html
<script src="//cdn.jsdelivr.net/npm/[email protected]/dist/protobuf.min.js"></script>

-Remember to replace the version tag with the exact release your project depends upon.

-The library supports CommonJS and AMD loaders and also exports globally as protobuf.

-### Distributions

-Where bundle size is a factor, there are additional stripped-down versions of the [full library][dist-full] (~19kb gzipped) available that exclude certain functionality:

-* When working with JSON descriptors (i.e. generated by pbjs) and/or reflection only, see the [light library][dist-light] (~16kb gzipped) that excludes the parser. CommonJS entry point is:

  • var protobuf = require("protobufjs/light");

-* When working with statically generated code only, see the [minimal library][dist-minimal] (~6.5kb gzipped) that also excludes reflection. CommonJS entry point is:

  • var protobuf = require("protobufjs/minimal");

| Distribution | Location
-|------------|-----------------------------------
-| Full | https://cdn.jsdelivr.net/npm/protobufjs/dist/
-| Light | https://cdn.jsdelivr.net/npm/protobufjs/dist/light/
-| Minimal | https://cdn.jsdelivr.net/npm/protobufjs/dist/minimal/
+|--------------|--------------------------------------------------------
+| Full | https://cdn.jsdelivr.net/npm/protobufjs/dist/
+| Light | https://cdn.jsdelivr.net/npm/protobufjs/dist/light/
+| Minimal | https://cdn.jsdelivr.net/npm/protobufjs/dist/minimal/
+
+All variants support CommonJS and AMD loaders and export globally as window.protobuf.

Usage

-Because JavaScript is a dynamically typed language, protobuf.js introduces the concept of a valid message in order to provide the best possible performance (and, as a side product, proper typings):
+Because JavaScript is a dynamically typed language, protobuf.js utilizes the concept of a valid message in order to provide the best possible performance (and, as a side product, proper typings):

Valid message

@@ -111,7 +98,7 @@ Because JavaScript is a dynamically typed language, protobuf.js introduces the c

There are two possible types of valid messages and the encoder is able to work with both of these for convenience:

-* Message instances (explicit instances of message classes with default values on their prototype) always (have to) satisfy the requirements of a valid message by design and
+* Message instances (explicit instances of message classes with default values on their prototype) naturally satisfy the requirements of a valid message and

  • Plain JavaScript objects that just so happen to be composed in a way satisfying the requirements of a valid message as well.

In a nutshell, the wire format writer understands the following types:
@@ -126,11 +113,11 @@ In a nutshell, the wire format writer understands the following types:
| bytes | Uint8Array (optimal)
Buffer (optimal under node)
Array.<number> (8 bit integers) | base64.decode(value) if a string
Object with non-zero .length is assumed to be buffer-like
| enum | number (32 bit integer) | Looks up the numeric id if a string
| message | Valid message | Message.fromObject(value)
+| repeated T | Array<T> | Copy
+| map<K, V> | Object<K,V> | Copy

  • Explicit undefined and null are considered as not set if the field is optional.
    -* Repeated fields are Array.<T>.
    -* Map fields are Object.<string,T> with the key being the string representation of the respective value or an 8 characters long binary hash string for Long-likes.
    -* Types marked as optimal provide the best performance because no conversion step (i.e. number to low and high bits or base64 string to buffer) is required.
    +* Maps are objects where the key is the string representation of the respective value or an 8 characters long hash string for Long-likes.

Toolset

@@ -210,7 +197,7 @@ For reference, the following diagram aims to display relationships between the d

Toolset Diagram

-> In other words: verify indicates that calling create or encode directly on the plain object will [result in a valid message respectively] succeed. fromObject, on the other hand, does conversion from a broader range of plain objects to create valid messages. (ref)
+> In other words: verify indicates that calling create or encode directly on the plain object will [result in a valid message respectively] succeed. fromObject, on the other hand, does conversion from a broader range of plain objects to create valid messages. (ref)

Examples

@@ -482,13 +469,13 @@ greeter.sayHello({ name: 'you' })
});


-There is also an [example for streaming RPC](https://github.com/dcodeIO/protobuf.js/blob/master/examples/streaming-rpc.js).
+There is also an [example for streaming RPC](https://github.com/protobufjs/protobuf.js/blob/master/examples/streaming-rpc.js).

Note that the service API is meant for clients. Implementing a server-side endpoint pretty much always requires transport channel (i.e. http, websocket, etc.) specific code with the only common denominator being that it decodes and encodes messages.

### Usage with TypeScript

-The library ships with its own [type definitions](https://github.com/dcodeIO/protobuf.js/blob/master/index.d.ts) and modern editors like [Visual Studio Code](https://code.visualstudio.com/) will automatically detect and use them for code completion.
+The library ships with its own [type definitions](https://github.com/protobufjs/protobuf.js/blob/master/index.d.ts) and modern editors like [Visual Studio Code](https://code.visualstudio.com/) will automatically detect and use them for code completion.

The npm package depends on [@types/node](https://www.npmjs.com/package/@types/node) because of `Buffer` and [@types/long](https://www.npmjs.com/package/@types/long) because of `Long`. If you are not building for node and/or not using long.js, it should be safe to exclude them manually.

@@ -595,18 +582,18 @@ Other notes:
* Default values must be specified as arguments to the decorator instead of using a property initializer for proper prototype behavior.
* Property names on decorated classes must not be renamed on compile time (i.e. by a minifier) because decorators just receive the original field name as a string.

-**ProTip!** Not as pretty, but you can [use decorators in plain JavaScript](https://github.com/dcodeIO/protobuf.js/blob/master/examples/js-decorators.js) as well.
+**ProTip!** Not as pretty, but you can [use decorators in plain JavaScript](https://github.com/protobufjs/protobuf.js/blob/master/examples/js-decorators.js) as well.

Additional documentation
------------------------

#### Protocol Buffers
-* [Google's Developer Guide](https://developers.google.com/protocol-buffers/docs/overview)
+* [Google's Developer Guide](https://protobuf.dev/overview/)

#### protobuf.js
* [API Documentation](https://protobufjs.github.io/protobuf.js)
-* [CHANGELOG](https://github.com/dcodeIO/protobuf.js/blob/master/CHANGELOG.md)
-* [Frequently asked questions](https://github.com/dcodeIO/protobuf.js/wiki) on our wiki
+* [CHANGELOG](https://github.com/protobufjs/protobuf.js/blob/master/CHANGELOG.md)
+* [Frequently asked questions](https://github.com/protobufjs/protobuf.js/wiki) on our wiki

#### Community
* [Questions and answers](http://stackoverflow.com/search?tab=newest&q=protobuf.js) on StackOverflow
@@ -666,13 +653,13 @@ These results are achieved by
* using node-specific functionality where beneficial and, of course
* avoiding unnecessary operations through splitting up [the toolset](#toolset).

-You can also run [the benchmark](https://github.com/dcodeIO/protobuf.js/blob/master/bench/index.js) ...
+You can also run [the benchmark](https://github.com/protobufjs/protobuf.js/blob/master/bench/index.js) ...

$> npm run bench


-and [the profiler](https://github.com/dcodeIO/protobuf.js/blob/master/bench/prof.js) yourself (the latter requires a recent version of node):
+and [the profiler](https://github.com/protobufjs/protobuf.js/blob/master/bench/prof.js) yourself (the latter requires a recent version of node):

$> npm run prof <encode|decode|encode-browser|decode-browser> [iterations=10000000]
@@ -686,10 +673,10 @@ Compatibility

  • Works in all modern and not-so-modern browsers except IE8.
  • Because the internals of this package do not rely on google/protobuf/descriptor.proto, options are parsed and presented literally.
  • If typed arrays are not supported by the environment, plain arrays will be used instead.
    -* Support for pre-ES5 environments (except IE8) can be achieved by using a polyfill.
    -* Support for Content Security Policy-restricted environments (like Chrome extensions without unsafe-eval) can be achieved by generating and using static code instead.
    +* Support for pre-ES5 environments (except IE8) can be achieved by using a polyfill.
    +* Support for Content Security Policy-restricted environments (like Chrome extensions without unsafe-eval) can be achieved by generating and using static code instead.
  • If a proper way to work with 64 bit values (uint64, int64 etc.) is required, just install long.js alongside this library. All 64 bit numbers will then be returned as a Long instance instead of a possibly unsafe JavaScript number (see).
    -* For descriptor.proto interoperability, see ext/descriptor
    +* For descriptor.proto interoperability, see ext/descriptor

Building

@@ -697,7 +684,7 @@ Building
To build the library or its components yourself, clone it from GitHub and install the development dependencies:

-$> git clone https://github.com/dcodeIO/protobuf.js.git
+$> git clone https://github.com/protobufjs/protobuf.js.git
$> cd protobuf.js
$> npm install

@@ -717,7 +704,7 @@ $> npm run docs
Building the TypeScript definition to index.d.ts:

-$> npm run types
+$> npm run build:types

Browserify integration

@@ -735,6 +722,6 @@ By default, protobuf.js integrates into any browserify build-process without req
protobuf.configure();


-* If you have any special requirements, there is [the bundler](https://github.com/dcodeIO/protobuf.js/blob/master/scripts/bundle.js) for reference.
+* If you have any special requirements, there is [the bundler](https://github.com/protobufjs/protobuf.js/blob/master/scripts/bundle.js) for reference.

**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
diff --git cli/CHANGELOG.md cli/CHANGELOG.md
index 40185284d..887c1ae62 100644
--- cli/CHANGELOG.md
+++ cli/CHANGELOG.md
@@ -1,5 +1,19 @@
# Changelog

+## [1.1.4](https://github.com/protobufjs/protobuf.js/compare/protobufjs-cli-v1.1.3...protobufjs-cli-v1.1.4) (2024-08-22)
+
+
+### Bug Fixes
+
+* include ([28e3334](https://github.com/protobufjs/protobuf.js/commit/28e333415d3c85687810e164125997d17baba0bd))
+
+## [1.1.3](https://github.com/protobufjs/protobuf.js/compare/protobufjs-cli-v1.1.2...protobufjs-cli-v1.1.3) (2024-08-16)
+
+
+### Bug Fixes
+
+* handle nullability for optional fields ([59569c1](https://github.com/protobufjs/protobuf.js/commit/59569c12c85c1c7b783ace9a71775b1d05a08e9c))
+
## [1.1.2](https://github.com/protobufjs/protobuf.js/compare/protobufjs-cli-v1.1.1...protobufjs-cli-v1.1.2) (2023-08-21)


diff --git cli/README.md cli/README.md
index e7f189007..912e8bcd7 100644
--- cli/README.md
+++ cli/README.md
@@ -68,6 +68,9 @@ Translates between file formats and generates static code.
--force-long     Enforces the use of 'Long' for s-/u-/int64 and s-/fixed64 fields.
--force-number   Enforces the use of 'number' for s-/u-/int64 and s-/fixed64 fields.
--force-message  Enforces the use of message instances instead of plain objects.
+  
+  --null-defaults  Default value for optional fields is null instead of zero value.
+  --null-semantics Make nullable fields match protobuf semantics (overrides --null-defaults).

usage: pbjs [options] file1.proto file2.json ...  (or pipe)  other | pbjs [options] -

diff --git cli/lib/tsd-jsdoc/publish.js cli/lib/tsd-jsdoc/publish.js
index f6dab9982..f29097e53 100644
--- cli/lib/tsd-jsdoc/publish.js
+++ cli/lib/tsd-jsdoc/publish.js
@@ -392,7 +392,7 @@ function writeInterfaceBody(element) {
if (element.tsType)
writeln(element.tsType.replace(/\r?\n|\r/g, "\n"));
else if (element.properties && element.properties.length)

  •    element.properties.forEach(writeProperty);
    
  •    element.properties.forEach((property) => writeProperty(property));
    
    --indent;
    write("}");
    }
    diff --git cli/package.json cli/package.json
    index b2166acf1..ab4cd1a77 100644
    --- cli/package.json
    +++ cli/package.json
    @@ -1,7 +1,7 @@
    {
    "name": "protobufjs-cli",
    "description": "Translates between file formats and generates static code as well as TypeScript definitions.",
  • "version": "1.1.2",
  • "version": "1.1.4",
    "author": "Daniel Wirtz [email protected]",
    "repository": {
    "type": "git",
    diff --git cli/pbjs.js cli/pbjs.js
    index 150a2b6f0..c276ce464 100644
    --- cli/pbjs.js
    +++ cli/pbjs.js
    @@ -41,7 +41,7 @@ exports.main = function main(args, callback) {
    "force-message": "strict-message"
    },
    string: [ "target", "out", "path", "wrap", "dependency", "root", "lint", "filter" ],
  •    boolean: [ "create", "encode", "decode", "verify", "convert", "delimited", "typeurl", "beautify", "comments", "service", "es6", "sparse", "keep-case", "alt-comment", "force-long", "force-number", "force-enum-string", "force-message", "null-defaults" ],
    
  •    boolean: [ "create", "encode", "decode", "verify", "convert", "delimited", "typeurl", "beautify", "comments", "service", "es6", "sparse", "keep-case", "alt-comment", "force-long", "force-number", "force-enum-string", "force-message", "null-defaults", "null-semantics"],
       default: {
           target: "json",
           create: true,
    

@@ -63,6 +63,7 @@ exports.main = function main(args, callback) {
"force-enum-string": false,
"force-message": false,
"null-defaults": false,

  •        "null-semantics": false
       }
    
    });

@@ -148,6 +149,7 @@ exports.main = function main(args, callback) {
" --force-message Enforces the use of message instances instead of plain objects.",
"",
" --null-defaults Default value for optional fields is null instead of zero value.",

  •            "  --null-semantics Make nullable fields match protobuf semantics (overrides --null-defaults).",
               "",
               "usage: " + chalk.bold.green("pbjs") + " [options] file1.proto file2.json ..." + chalk.gray("  (or pipe)  ") + "other | " + chalk.bold.green("pbjs") + " [options] -",
               ""
    

diff --git cli/targets/static.js cli/targets/static.js
index c130d9026..3b4cf05b3 100644
--- cli/targets/static.js
+++ cli/targets/static.js
@@ -311,9 +311,15 @@ function buildFunction(type, functionName, gen, scope) {
push("};");
}

-function toJsType(field) {
+function toJsType(field, parentIsInterface = false) {
var type;

  • // With null semantics, interfaces are composed from interfaces and messages from messages
  • // Without null semantics, child types depend on the --force-message flag
  • var asInterface = config["null-semantics"]
  •    ? parentIsInterface && !(field.resolvedType instanceof protobuf.Enum)
    
  •    : !(field.resolvedType instanceof protobuf.Enum || config.forceMessage);
    
  • switch (field.type) {
    case "double":
    case "float":
    @@ -341,10 +347,12 @@ function toJsType(field) {
    type = "Uint8Array";
    break;
    default:
  •        if (field.resolve().resolvedType)
    
  •            type = exportName(field.resolvedType, !(field.resolvedType instanceof protobuf.Enum || config.forceMessage));
    
  •        else
    
  •        if (field.resolve().resolvedType) {
    
  •            type = exportName(field.resolvedType, asInterface);
    
  •        }
    
  •        else {
               type = "*"; // should not happen
    
  •        }
           break;
    
    }
    if (field.map)
    @@ -354,8 +362,72 @@ function toJsType(field) {
    return type;
    }

+function syntaxForType(type) {
+

  • var syntax = null;
  • var namespace = type;
  • while (syntax === null && namespace !== null) {
  •    if (namespace.options != null && "syntax" in namespace.options) {
    
  •        syntax = namespace.options["syntax"];
    
  •    }
    
  •    else {
    
  •        namespace = namespace.parent;
    
  •    }
    
  • }
  • return syntax !== null ? syntax : "proto2";
    +}

+function isExplicitPresence(field, syntax) {
+

  • // In proto3, optional fields are explicit
  • if (syntax === "proto3") {
  •    return field.options != null && field.options["proto3_optional"] === true;
    
  • }
  • // In proto2, fields are explicitly optional if they are not part of a map, array or oneOf group
  • if (syntax === "proto2") {
  •    return field.optional && !(field.partOf || field.repeated || field.map);
    
  • }
  • throw new Error("Unknown proto syntax: [" + syntax + "]");
    +}

+function isImplicitPresence(field, syntax) {
+

  • // In proto3, everything not marked optional has implicit presence (including maps and repeated fields)
  • if (syntax === "proto3") {
  •    return field.options == null || field.options["proto3_optional"] !== true;
    
  • }
  • // In proto2, nothing has implicit presence
  • if (syntax === "proto2") {
  •    return false;
    
  • }
  • throw new Error("Unknown proto syntax: [" + syntax + "]");
    +}

+function isOptionalOneOf(oneof, syntax) {
+

  • if (syntax === "proto2") {
  •    return false;
    
  • }
  • if (oneof.fieldsArray == null || oneof.fieldsArray.length !== 1) {
  •    return false;
    
  • }
  • var field = oneof.fieldsArray[0];
  • return field.options != null && field.options["proto3_optional"] === true;
    +}

function buildType(ref, type) {

  • var syntax = syntaxForType(type);
  • if (config.comments) {
    var typeDef = [
    "Properties of " + aOrAn(type.name) + ".",
    @@ -365,10 +437,30 @@ function buildType(ref, type) {
    type.fieldsArray.forEach(function(field) {
    var prop = util.safeProp(field.name); // either .name or ["name"]
    prop = prop.substring(1, prop.charAt(0) === "[" ? prop.length - 1 : prop.length);
  •        var jsType = toJsType(field);
    
  •        if (field.optional)
    
  •            jsType = jsType + "|null";
    
  •        typeDef.push("@property {" + jsType + "} " + (field.optional ? "[" + prop + "]" : prop) + " " + (field.comment || type.name + " " + field.name));
    
  •        var jsType = toJsType(field, /* parentIsInterface = */ true);
    
  •        var nullable = false;
    
  •        if (config["null-semantics"]) {
    
  •            // With semantic nulls, only explicit optional fields and one-of members can be set to null
    
  •            // Implicit fields (proto3), maps and lists can be omitted, but if specified must be non-null
    
  •            // Implicit fields will take their default value when the message is constructed
    
  •            if (isExplicitPresence(field, syntax) || field.partOf) {
    
  •                jsType = jsType + "|null|undefined";
    
  •                nullable = true;
    
  •            }
    
  •            else if (isImplicitPresence(field, syntax) || field.repeated || field.map) {
    
  •                jsType = jsType + "|undefined";
    
  •                nullable = true;
    
  •            }
    
  •        }
    
  •        else {
    
  •            // Without semantic nulls, everything is optional in proto3
    
  •            // Do not allow |undefined to keep backwards compatibility
    
  •            if (field.optional) {
    
  •                jsType = jsType + "|null";
    
  •                nullable = true;
    
  •            }
    
  •        }
    
  •        typeDef.push("@property {" + jsType + "} " + (nullable ? "[" + prop + "]" : prop) + " " + (field.comment || type.name + " " + field.name));
       });
       push("");
       pushComment(typeDef);
    

@@ -393,9 +485,22 @@ function buildType(ref, type) {
var prop = util.safeProp(field.name);
if (config.comments) {
push("");

  •        var jsType = toJsType(field);
    
  •        if (field.optional && !field.map && !field.repeated && (field.resolvedType instanceof Type || config["null-defaults"]) || field.partOf)
    
  •            jsType = jsType + "|null|undefined";
    
  •        var jsType = toJsType(field, /* parentIsInterface = */ false);
    
  •        if (config["null-semantics"]) {
    
  •            // With semantic nulls, fields are nullable if they are explicitly optional or part of a one-of
    
  •            // Maps, repeated values and fields with implicit defaults are never null after construction
    
  •            // Members are never undefined, at a minimum they are initialized to null
    
  •            if (isExplicitPresence(field, syntax) || field.partOf) {
    
  •                jsType = jsType + "|null";
    
  •            }
    
  •        }
    
  •        else {
    
  •            // Without semantic nulls, everything is optional in proto3
    
  •            // Keep |undefined for backwards compatibility
    
  •            if (field.optional && !field.map && !field.repeated && (field.resolvedType instanceof Type || config["null-defaults"]) || field.partOf) {
    
  •                jsType = jsType + "|null|undefined";
    
  •            }
    
  •        }
           pushComment([
               field.comment || type.name + " " + field.name + ".",
               "@member {" + jsType + "} " + field.name,
    

@@ -406,11 +511,16 @@ function buildType(ref, type) {
push("");
firstField = false;
}

  •    // With semantic nulls, only explict optional fields and one-of members are null by default
    
  •    // Otherwise use field.optional, which doesn't consider proto3, maps, repeated fields etc.
    
  •    var nullDefault = config["null-semantics"]
    
  •        ? isExplicitPresence(field, syntax)
    
  •        : field.optional && config["null-defaults"];
       if (field.repeated)
           push(escapeName(type.name) + ".prototype" + prop + " = $util.emptyArray;"); // overwritten in constructor
       else if (field.map)
           push(escapeName(type.name) + ".prototype" + prop + " = $util.emptyObject;"); // overwritten in constructor
    
  •    else if (field.partOf || field.optional && config["null-defaults"])
    
  •    else if (field.partOf || nullDefault)
           push(escapeName(type.name) + ".prototype" + prop + " = null;"); // do not set default value for oneof members
       else if (field.long)
           push(escapeName(type.name) + ".prototype" + prop + " = $util.Long ? $util.Long.fromBits("
    

@@ -436,12 +546,17 @@ function buildType(ref, type) {
}
oneof.resolve();
push("");

  •    pushComment([
    
  •        oneof.comment || type.name + " " + oneof.name + ".",
    
  •        "@member {" + oneof.oneof.map(JSON.stringify).join("|") + "|undefined} " + escapeName(oneof.name),
    
  •        "@memberof " + exportName(type),
    
  •        "@instance"
    
  •    ]);
    
  •    if (isOptionalOneOf(oneof, syntax)) {
    
  •        push("// Virtual OneOf for proto3 optional field");
    
  •    }
    
  •    else {
    
  •        pushComment([
    
  •            oneof.comment || type.name + " " + oneof.name + ".",
    
  •            "@member {" + oneof.oneof.map(JSON.stringify).join("|") + "|undefined} " + escapeName(oneof.name),
    
  •            "@memberof " + exportName(type),
    
  •            "@instance"
    
  •        ]);
    
  •    }
       push("Object.defineProperty(" + escapeName(type.name) + ".prototype, " + JSON.stringify(oneof.name) +", {");
       ++indent;
           push("get: $util.oneOfGetter($oneOfFields = [" + oneof.oneof.map(JSON.stringify).join(", ") + "]),");
    

diff --git index.d.ts index.d.ts
index 750ad2f73..0744761c8 100644
--- index.d.ts
+++ index.d.ts
@@ -1698,7 +1698,7 @@ export interface IType extends INamespace {
extensions?: number[][];

 /** Reserved ranges */
  • reserved?: number[][];
  • reserved?: (number[]|string)[];

    /** Whether a legacy group or not */
    group?: boolean;
    diff --git package.json package.json
    index 37c744ff8..747b3e05a 100644
    --- package.json
    +++ package.json
    @@ -1,6 +1,6 @@
    {
    "name": "protobufjs",

  • "version": "7.2.5",
  • "version": "7.4.0",
    "versionScheme": "~",
    "description": "Protocol Buffers for JavaScript (& TypeScript).",
    "author": "Daniel Wirtz [email protected]",
    @@ -40,6 +40,7 @@
    "lint:types": "tslint "/*.d.ts" -e "/node_modules/**" -t stylish -c config/tslint.json",
    "pages": "node scripts/pages",
    "prepublish": "cd cli && npm install && cd .. && npm run build",
  • "prepublishOnly": "cd cli && npm install && cd .. && npm run build",
    "postinstall": "node scripts/postinstall",
    "prof": "node bench/prof",
    "test": "npm run test:sources && npm run test:types",
    diff --git src/parse.js src/parse.js
    index 739f3265e..6e188b162 100644
    --- src/parse.js
    +++ src/parse.js
    @@ -144,7 +144,24 @@ function parse(source, root, options) {
    else
    target.push([ start = parseId(next()), skip("to", true) ? parseId(next()) : start ]);
    } while (skip(",", true));
  •    skip(";");
    
  •    var dummy = {options: undefined};
    
  •    dummy.setOption = function(name, value) {
    
  •      if (this.options === undefined) this.options = {};
    
  •      this.options[name] = value;
    
  •    };
    
  •    ifBlock(
    
  •        dummy,
    
  •        function parseRange_block(token) {
    
  •          /* istanbul ignore else */
    
  •          if (token === "option") {
    
  •            parseOption(dummy, token);  // skip
    
  •            skip(";");
    
  •          } else
    
  •            throw illegal(token);
    
  •        },
    
  •        function parseRange_line() {
    
  •          parseInlineOptions(dummy);  // skip
    
  •        });
    

    }

    function parseNumber(token, insideTryCatch) {
    @@ -246,6 +263,10 @@ function parse(source, root, options) {
    if (!isProto3 && syntax !== "proto2")
    throw illegal(syntax, "syntax");

  •    // Syntax is needed to understand the meaning of the optional field rule
    
  •    // Otherwise the meaning is ambiguous between proto2 and proto3
    
  •    root.setOption("syntax", syntax);
    
  •    skip(";");
    

    }

diff --git src/root.js src/root.js
index 9441a7fc3..2776f96e4 100644
--- src/root.js
+++ src/root.js
@@ -98,10 +98,10 @@ Root.prototype.load = function load(filename, options, callback) {
/* istanbul ignore if */
if (!callback)
return;

  •    var cb = callback;
    
  •    callback = null;
       if (sync)
           throw err;
    
  •    var cb = callback;
    
  •    callback = null;
       cb(err, root);
    
    }

diff --git src/type.js src/type.js
index 2e7bda49b..b477a4ee2 100644
--- src/type.js
+++ src/type.js
@@ -224,7 +224,7 @@ function clearCache(type) {

  • @Property {Object.<string,IOneOf>} [oneofs] Oneof descriptors
  • @Property {Object.<string,IField>} fields Field descriptors
  • @Property {number[][]} [extensions] Extension ranges
    • @Property {number[][]} [reserved] Reserved ranges
    • @Property {Array.<number[]|string>} [reserved] Reserved ranges
    • @Property {boolean} [group=false] Whether a legacy group or not
      */

diff --git tests/api_root.js tests/api_root.js
index 6e9814ddb..9125d3aa8 100644
--- tests/api_root.js
+++ tests/api_root.js
@@ -67,6 +67,29 @@ tape.test("reflected roots", function(test) {
});
});

  • test.test(test.name + " - missing import", function(test) {
  •    var root = new Root();
    
  •    test.plan(2);
    
  •    root.load("tests/data/badimport.proto", function(err) {
    
  •        test.ok(err, "should return an error when an imported file does not exist");
    
  •        test.match(err.toString(), /nonexistent\.proto/, "should mention the file name which was not found");
    
  •        test.end();
    
  •    });
    
  • });
  • test.test(test.name + " - missing import, sync load", function(test) {
  •    var root = new Root();
    
  •    test.plan(2);
    
  •    try {
    
  •        root.loadSync("tests/data/badimport.proto");
    
  •        root.resolveAll();
    
  •    } catch (err) {
    
  •        test.ok(err, "should return an error when an imported file does not exist");
    
  •        test.match(err.toString(), /nonexistent\.proto/, "should mention the file name which was not found");
    
  •    }
    
  •    test.end();
    
  • });
  • test.test(test.name + " - skipped", function(test) {
    var root = new Root();
    root.resolvePath = function() {
    diff --git tests/cli.js tests/cli.js
    index 4e27dfc80..3208edfc1 100644
    --- tests/cli.js
    +++ tests/cli.js
    @@ -165,6 +165,78 @@ tape.test("with null-defaults, absent optional fields have null values", functio
    });

+tape.test("with --null-semantics, optional fields are handled correctly in proto2", function(test) {

  • cliTest(test, function() {
  •    var root = protobuf.loadSync("tests/data/cli/null-defaults.proto");
    
  •    root.resolveAll();
    
  •    var staticTarget = require("../cli/targets/static");
    
  •    staticTarget(root, {
    
  •        create: true,
    
  •        decode: true,
    
  •        encode: true,
    
  •        convert: true,
    
  •        comments: true,
    
  •        "null-semantics": true,
    
  •    }, function(err, jsCode) {
    
  •        test.error(err, 'static code generation worked');
    
  •        test.ok(jsCode.includes("@property {OptionalFields.ISubMessage|null|undefined} [a] OptionalFields a"), "Property for a should use an interface")
    
  •        test.ok(jsCode.includes("@member {OptionalFields.SubMessage|null} a"), "Member for a should use a message type")
    
  •        test.ok(jsCode.includes("OptionalFields.prototype.a = null;"), "Initializer for a should be null")
    
  •        test.ok(jsCode.includes("@property {number|null|undefined} [c] OptionalFields c"), "Property for c should be nullable")
    
  •        test.ok(jsCode.includes("@member {number|null} c"), "Member for c should be nullable")
    
  •        test.ok(jsCode.includes("OptionalFields.prototype.c = null;"), "Initializer for c should be null")
    
  •        test.ok(jsCode.includes("@property {number} d OptionalFields d"), "Property for d should not be nullable")
    
  •        test.ok(jsCode.includes("@member {number} d"), "Member for d should not be nullable")
    
  •        test.ok(jsCode.includes("OptionalFields.prototype.d = 0;"), "Initializer for d should be zero")
    
  •        test.end();
    
  •    });
    
  • });
    +});

+tape.test("with --null-semantics, optional fields are handled correctly in proto3", function(test) {

  • cliTest(test, function() {
  •    var root = protobuf.loadSync("tests/data/cli/null-defaults-proto3.proto");
    
  •    root.resolveAll();
    
  •    var staticTarget = require("../cli/targets/static");
    
  •    staticTarget(root, {
    
  •        create: true,
    
  •        decode: true,
    
  •        encode: true,
    
  •        convert: true,
    
  •        comments: true,
    
  •        "null-semantics": true,
    
  •    }, function(err, jsCode) {
    
  •        test.error(err, 'static code generation worked');
    
  •        test.ok(jsCode.includes("@property {OptionalFields.ISubMessage|null|undefined} [a] OptionalFields a"), "Property for a should use an interface")
    
  •        test.ok(jsCode.includes("@member {OptionalFields.SubMessage|null} a"), "Member for a should use a message type")
    
  •        test.ok(jsCode.includes("OptionalFields.prototype.a = null;"), "Initializer for a should be null")
    
  •        test.ok(jsCode.includes("@property {number|null|undefined} [c] OptionalFields c"), "Property for c should be nullable")
    
  •        test.ok(jsCode.includes("@member {number|null} c"), "Member for c should be nullable")
    
  •        test.ok(jsCode.includes("OptionalFields.prototype.c = null;"), "Initializer for c should be null")
    
  •        test.ok(jsCode.includes("@property {number|undefined} [d] OptionalFields d"), "Property for d should be optional but not nullable")
    
  •        test.ok(jsCode.includes("@member {number} d"), "Member for d should not be nullable")
    
  •        test.ok(jsCode.includes("OptionalFields.prototype.d = 0;"), "Initializer for d should be zero")
    
  •        test.end();
    
  •    });
    
  • });
    +});

tape.test("pbjs generates static code with message filter", function (test) {
cliTest(test, function () {
var root = protobuf.loadSync("tests/data/cli/test-filter.proto");
diff --git a/tests/data/badimport.proto b/tests/data/badimport.proto
new file mode 100644
index 000000000..f11caaf6b
--- /dev/null
+++ tests/data/badimport.proto
@@ -0,0 +1,7 @@
+syntax = "proto3";
+
+import "nonexistent.proto";
+
+message Message {

  • NonExistent field = 1;
    +}
    diff --git a/tests/data/cli/null-defaults-proto3.proto b/tests/data/cli/null-defaults-proto3.proto
    new file mode 100644
    index 000000000..4a17e8bd4
    --- /dev/null
    +++ tests/data/cli/null-defaults-proto3.proto
    @@ -0,0 +1,12 @@
    +syntax = "proto3";

+message OptionalFields {

  • message SubMessage {
  • string a = 1;
  • }
  • optional SubMessage a = 1;
  • optional string b = 2;
  • optional uint32 c = 3;
  • uint32 d = 4;
    +}
    diff --git tests/data/cli/null-defaults.proto tests/data/cli/null-defaults.proto
    index 6a140b1e2..d182a01c3 100644
    --- tests/data/cli/null-defaults.proto
    +++ tests/data/cli/null-defaults.proto
    @@ -8,4 +8,5 @@ message OptionalFields {
    optional SubMessage a = 1;
    optional string b = 2;
    optional uint32 c = 3;
  • required uint32 d = 4;
    }
    diff --git tests/data/google/protobuf/descriptor.proto tests/data/google/protobuf/descriptor.proto
    index 747d90cfc..561d9629e 100644
    --- tests/data/google/protobuf/descriptor.proto
    +++ tests/data/google/protobuf/descriptor.proto
    @@ -101,6 +101,8 @@ message DescriptorProto {
    message ExtensionRange {
    optional int32 start = 1;
    optional int32 end = 2;
  • optional ExtensionRangeOptions options = 3;
    }
    repeated ExtensionRange extension_range = 5;

@@ -121,6 +123,63 @@ message DescriptorProto {
repeated string reserved_name = 10;
}

+message ExtensionRangeOptions {

  • // The parser stores options it doesn't recognize here. See above.
  • repeated UninterpretedOption uninterpreted_option = 999;
  • message Declaration {
  • // The extension number declared within the extension range.
  • optional int32 number = 1;
  • // The fully-qualified name of the extension field. There must be a leading
  • // dot in front of the full name.
  • optional string full_name = 2;
  • // The fully-qualified type name of the extension field. Unlike
  • // Metadata.type, Declaration.type must have a leading dot for messages
  • // and enums.
  • optional string type = 3;
  • // If true, indicates that the number is reserved in the extension range,
  • // and any extension field with the number will fail to compile. Set this
  • // when a declared extension field is deleted.
  • optional bool reserved = 5;
  • // If true, indicates that the extension must be defined as repeated.
  • // Otherwise the extension must be defined as optional.
  • optional bool repeated = 6;
  • reserved 4; // removed is_repeated
  • }
  • // For external users: DO NOT USE. We are in the process of open sourcing
  • // extension declaration and executing internal cleanups before it can be
  • // used externally.
  • repeated Declaration declaration = 2 [retention = RETENTION_SOURCE];
  • // The verification state of the extension range.
  • enum VerificationState {
  • // All the extensions of the range must be declared.
  • DECLARATION = 0;
  • UNVERIFIED = 1;
  • }
  • // The verification state of the range.
  • // TODO(b/278783756): flip the default to DECLARATION once all empty ranges
  • // are marked as UNVERIFIED.
  • optional VerificationState verification = 3
  •  [default = UNVERIFIED, retention = RETENTION_SOURCE];
    
  • // Clients can define custom options in extensions of this message. See above.
  • // BEGIN GOOGLE-INTERNAL
  • // Extension numbers > 530,000,000 must be forward-declared in
  • // google3/third_party/protobuf/extdecl_extension_range_options.h. See
  • // go/extension-declaration-reserved-numbers for more information.
  • // END GOOGLE-INTERNAL
  • extensions 1000 to max;
    +}

// Describes a field within a message.
message FieldDescriptorProto {
enum Type {
@@ -813,4 +872,4 @@ message GeneratedCodeInfo {
// the last relevant byte (so the length of the text = end - begin).
optional int32 end = 4;
}
-}
\ No newline at end of file
+}
diff --git tests/data/uncommon.proto tests/data/uncommon.proto
index fa9fa037f..764e07801 100644
--- tests/data/uncommon.proto
+++ tests/data/uncommon.proto
@@ -47,6 +47,13 @@ message Test2 {
extend Test;
extend Test{};
extend Test{required int32 a=1;} // not validated by the parser

  • extend Test{Test inner_ext=1000;} // not validated by the parser
  • extensions 1000 to 1999 [declaration = {
  •    number: 1000
    
  •    full_name: 'uncommon.Test.inner_ext'
    
  •    type: 'uncommon.Test'
    
  • }];
    };

enum Test3;


</details>

### Description
This is a major update to protobuf.js that includes several significant changes around null handling semantics, documentation improvements, and bug fixes. The PR updates the version from 7.2.5 to 7.4.0.

<details>
<summary><i>Changes</i></summary>

### Changes

#### Core Changes
1. Added new null semantics options:
   - `--null-defaults`: Makes optional fields default to null instead of zero value
   - `--null-semantics`: Makes nullable fields match protobuf semantics
   
2. Improved handling of optional fields:
   - Better distinction between proto2 and proto3 optional field handling
   - Added support for extension range options
   - Fixed nullability handling for optional fields

#### Documentation Changes (`README.md`)
- Updated badges and links
- Modernized documentation style and content
- Improved installation and usage instructions
- Updated TypeScript usage examples
- Reorganized distribution information

#### CLI Changes
- Added support for new null semantics options
- Updated CLI documentation
- Fixed static code generation for nullable fields

#### Testing
- Added new tests for null semantics
- Added tests for missing import scenarios
- Enhanced test coverage for optional fields in both proto2 and proto3

```mermaid
sequenceDiagram
    participant User
    participant CLI
    participant Parser
    participant Generator
    participant Output

    User->>CLI: Run protobuf.js with options
    CLI->>Parser: Parse .proto files
    Parser->>Parser: Determine syntax (proto2/proto3)
    Parser->>Parser: Handle optional fields
    Parser->>Generator: Pass AST
    
    alt null-semantics enabled
        Generator->>Generator: Apply proto3 nullability rules
    else
        Generator->>Generator: Apply legacy nullability rules
    end
    
    Generator->>Output: Generate TypeScript/JavaScript
    Output->>User: Return generated code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

0 participants