diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c005ec0f2..36005b3e6 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{".":"7.2.6","cli":"1.1.2"} +{".":"7.3.0","cli":"1.1.2"} diff --git a/CHANGELOG.md b/CHANGELOG.md index 700191ed3..7ef3560c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [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) diff --git a/package-lock.json b/package-lock.json index 80637165f..f69330313 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "protobufjs", - "version": "7.2.6", + "version": "7.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "protobufjs", - "version": "7.2.6", + "version": "7.3.0", "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { diff --git a/package.json b/package.json index de0e004bc..8a0e4cbbf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "protobufjs", - "version": "7.2.6", + "version": "7.3.0", "versionScheme": "~", "description": "Protocol Buffers for JavaScript (& TypeScript).", "author": "Daniel Wirtz ", diff --git a/src/parse.js b/src/parse.js index 739f3265e..f5f070e3f 100644 --- a/src/parse.js +++ b/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) { diff --git a/tests/data/google/protobuf/descriptor.proto b/tests/data/google/protobuf/descriptor.proto index 747d90cfc..561d9629e 100644 --- a/tests/data/google/protobuf/descriptor.proto +++ b/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 a/tests/data/uncommon.proto b/tests/data/uncommon.proto index fa9fa037f..764e07801 100644 --- a/tests/data/uncommon.proto +++ b/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;