protobufjs 7.4.0 → 7.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/protobuf.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * protobuf.js v7.4.0 (c) 2016, daniel wirtz
3
- * compiled thu, 22 aug 2024 20:30:39 utc
2
+ * protobuf.js v7.5.0 (c) 2016, daniel wirtz
3
+ * compiled tue, 15 apr 2025 17:05:18 utc
4
4
  * licensed under the bsd-3-clause license
5
5
  * see: https://github.com/dcodeio/protobuf.js for details
6
6
  */
@@ -1831,16 +1831,14 @@ function missing(field) {
1831
1831
  */
1832
1832
  function decoder(mtype) {
1833
1833
  /* eslint-disable no-unexpected-multiline */
1834
- var gen = util.codegen(["r", "l"], mtype.name + "$decode")
1834
+ var gen = util.codegen(["r", "l", "e"], mtype.name + "$decode")
1835
1835
  ("if(!(r instanceof Reader))")
1836
1836
  ("r=Reader.create(r)")
1837
1837
  ("var c=l===undefined?r.len:r.pos+l,m=new this.ctor" + (mtype.fieldsArray.filter(function(field) { return field.map; }).length ? ",k,value" : ""))
1838
1838
  ("while(r.pos<c){")
1839
- ("var t=r.uint32()");
1840
- if (mtype.group) gen
1841
- ("if((t&7)===4)")
1842
- ("break");
1843
- gen
1839
+ ("var t=r.uint32()")
1840
+ ("if(t===e)")
1841
+ ("break")
1844
1842
  ("switch(t>>>3){");
1845
1843
 
1846
1844
  var i = 0;
@@ -1906,15 +1904,15 @@ function decoder(mtype) {
1906
1904
  ("}else");
1907
1905
 
1908
1906
  // Non-packed
1909
- if (types.basic[type] === undefined) gen(field.resolvedType.group
1910
- ? "%s.push(types[%i].decode(r))"
1907
+ if (types.basic[type] === undefined) gen(field.delimited
1908
+ ? "%s.push(types[%i].decode(r,undefined,((t&~7)|4)))"
1911
1909
  : "%s.push(types[%i].decode(r,r.uint32()))", ref, i);
1912
1910
  else gen
1913
1911
  ("%s.push(r.%s())", ref, type);
1914
1912
 
1915
1913
  // Non-repeated
1916
- } else if (types.basic[type] === undefined) gen(field.resolvedType.group
1917
- ? "%s=types[%i].decode(r)"
1914
+ } else if (types.basic[type] === undefined) gen(field.delimited
1915
+ ? "%s=types[%i].decode(r,undefined,((t&~7)|4))"
1918
1916
  : "%s=types[%i].decode(r,r.uint32())", ref, i);
1919
1917
  else gen
1920
1918
  ("%s=r.%s()", ref, type);
@@ -1961,7 +1959,7 @@ var Enum = require(15),
1961
1959
  * @ignore
1962
1960
  */
1963
1961
  function genTypePartial(gen, field, fieldIndex, ref) {
1964
- return field.resolvedType.group
1962
+ return field.delimited
1965
1963
  ? gen("types[%i].encode(%s,w.uint32(%i)).uint32(%i)", fieldIndex, ref, (field.id << 3 | 3) >>> 0, (field.id << 3 | 4) >>> 0)
1966
1964
  : gen("types[%i].encode(%s,w.uint32(%i).fork()).ldelim()", fieldIndex, ref, (field.id << 3 | 2) >>> 0);
1967
1965
  }
@@ -2104,6 +2102,12 @@ function Enum(name, values, options, comment, comments, valuesOptions) {
2104
2102
  */
2105
2103
  this.valuesOptions = valuesOptions;
2106
2104
 
2105
+ /**
2106
+ * Resolved values features, if any
2107
+ * @type {Object<string, Object<string, *>>|undefined}
2108
+ */
2109
+ this._valuesFeatures = {};
2110
+
2107
2111
  /**
2108
2112
  * Reserved ranges, if any.
2109
2113
  * @type {Array.<number[]|string>}
@@ -2120,6 +2124,21 @@ function Enum(name, values, options, comment, comments, valuesOptions) {
2120
2124
  this.valuesById[ this.values[keys[i]] = values[keys[i]] ] = keys[i];
2121
2125
  }
2122
2126
 
2127
+ /**
2128
+ * @override
2129
+ */
2130
+ Enum.prototype._resolveFeatures = function _resolveFeatures(edition) {
2131
+ edition = this._edition || edition;
2132
+ ReflectionObject.prototype._resolveFeatures.call(this, edition);
2133
+
2134
+ Object.keys(this.values).forEach(key => {
2135
+ var parentFeaturesCopy = Object.assign({}, this._features);
2136
+ this._valuesFeatures[key] = Object.assign(parentFeaturesCopy, this.valuesOptions && this.valuesOptions[key] && this.valuesOptions[key].features);
2137
+ });
2138
+
2139
+ return this;
2140
+ };
2141
+
2123
2142
  /**
2124
2143
  * Enum descriptor.
2125
2144
  * @interface IEnum
@@ -2137,6 +2156,9 @@ function Enum(name, values, options, comment, comments, valuesOptions) {
2137
2156
  Enum.fromJSON = function fromJSON(name, json) {
2138
2157
  var enm = new Enum(name, json.values, json.options, json.comment, json.comments);
2139
2158
  enm.reserved = json.reserved;
2159
+ if (json.edition)
2160
+ enm._edition = json.edition;
2161
+ enm._defaultEdition = "proto3"; // For backwards-compatibility.
2140
2162
  return enm;
2141
2163
  };
2142
2164
 
@@ -2148,6 +2170,7 @@ Enum.fromJSON = function fromJSON(name, json) {
2148
2170
  Enum.prototype.toJSON = function toJSON(toJSONOptions) {
2149
2171
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
2150
2172
  return util.toObject([
2173
+ "edition" , this._editionToJSON(),
2151
2174
  "options" , this.options,
2152
2175
  "valuesOptions" , this.valuesOptions,
2153
2176
  "values" , this.values,
@@ -2283,7 +2306,11 @@ var ruleRe = /^required|optional|repeated$/;
2283
2306
  * @throws {TypeError} If arguments are invalid
2284
2307
  */
2285
2308
  Field.fromJSON = function fromJSON(name, json) {
2286
- return new Field(name, json.id, json.type, json.rule, json.extend, json.options, json.comment);
2309
+ var field = new Field(name, json.id, json.type, json.rule, json.extend, json.options, json.comment);
2310
+ if (json.edition)
2311
+ field._edition = json.edition;
2312
+ field._defaultEdition = "proto3"; // For backwards-compatibility.
2313
+ return field;
2287
2314
  };
2288
2315
 
2289
2316
  /**
@@ -2353,18 +2380,6 @@ function Field(name, id, type, rule, extend, options, comment) {
2353
2380
  */
2354
2381
  this.extend = extend || undefined; // toJSON
2355
2382
 
2356
- /**
2357
- * Whether this field is required.
2358
- * @type {boolean}
2359
- */
2360
- this.required = rule === "required";
2361
-
2362
- /**
2363
- * Whether this field is optional.
2364
- * @type {boolean}
2365
- */
2366
- this.optional = !this.required;
2367
-
2368
2383
  /**
2369
2384
  * Whether this field is repeated.
2370
2385
  * @type {boolean}
@@ -2431,13 +2446,6 @@ function Field(name, id, type, rule, extend, options, comment) {
2431
2446
  */
2432
2447
  this.declaringField = null;
2433
2448
 
2434
- /**
2435
- * Internally remembers whether this field is packed.
2436
- * @type {boolean|null}
2437
- * @private
2438
- */
2439
- this._packed = null;
2440
-
2441
2449
  /**
2442
2450
  * Comment for this field.
2443
2451
  * @type {string|null}
@@ -2446,17 +2454,69 @@ function Field(name, id, type, rule, extend, options, comment) {
2446
2454
  }
2447
2455
 
2448
2456
  /**
2449
- * Determines whether this field is packed. Only relevant when repeated and working with proto2.
2457
+ * Determines whether this field is required.
2458
+ * @name Field#required
2459
+ * @type {boolean}
2460
+ * @readonly
2461
+ */
2462
+ Object.defineProperty(Field.prototype, "required", {
2463
+ get: function() {
2464
+ return this._features.field_presence === "LEGACY_REQUIRED";
2465
+ }
2466
+ });
2467
+
2468
+ /**
2469
+ * Determines whether this field is not required.
2470
+ * @name Field#optional
2471
+ * @type {boolean}
2472
+ * @readonly
2473
+ */
2474
+ Object.defineProperty(Field.prototype, "optional", {
2475
+ get: function() {
2476
+ return !this.required;
2477
+ }
2478
+ });
2479
+
2480
+ /**
2481
+ * Determines whether this field uses tag-delimited encoding. In proto2 this
2482
+ * corresponded to group syntax.
2483
+ * @name Field#delimited
2484
+ * @type {boolean}
2485
+ * @readonly
2486
+ */
2487
+ Object.defineProperty(Field.prototype, "delimited", {
2488
+ get: function() {
2489
+ return this.resolvedType instanceof Type &&
2490
+ this._features.message_encoding === "DELIMITED";
2491
+ }
2492
+ });
2493
+
2494
+ /**
2495
+ * Determines whether this field is packed. Only relevant when repeated.
2450
2496
  * @name Field#packed
2451
2497
  * @type {boolean}
2452
2498
  * @readonly
2453
2499
  */
2454
2500
  Object.defineProperty(Field.prototype, "packed", {
2455
2501
  get: function() {
2456
- // defaults to packed=true if not explicity set to false
2457
- if (this._packed === null)
2458
- this._packed = this.getOption("packed") !== false;
2459
- return this._packed;
2502
+ return this._features.repeated_field_encoding === "PACKED";
2503
+ }
2504
+ });
2505
+
2506
+ /**
2507
+ * Determines whether this field tracks presence.
2508
+ * @name Field#hasPresence
2509
+ * @type {boolean}
2510
+ * @readonly
2511
+ */
2512
+ Object.defineProperty(Field.prototype, "hasPresence", {
2513
+ get: function() {
2514
+ if (this.repeated || this.map) {
2515
+ return false;
2516
+ }
2517
+ return this.partOf || // oneofs
2518
+ this.declaringField || this.extensionField || // extensions
2519
+ this._features.field_presence !== "IMPLICIT";
2460
2520
  }
2461
2521
  });
2462
2522
 
@@ -2464,8 +2524,6 @@ Object.defineProperty(Field.prototype, "packed", {
2464
2524
  * @override
2465
2525
  */
2466
2526
  Field.prototype.setOption = function setOption(name, value, ifNotSet) {
2467
- if (name === "packed") // clear cached before setting
2468
- this._packed = null;
2469
2527
  return ReflectionObject.prototype.setOption.call(this, name, value, ifNotSet);
2470
2528
  };
2471
2529
 
@@ -2493,6 +2551,7 @@ Field.prototype.setOption = function setOption(name, value, ifNotSet) {
2493
2551
  Field.prototype.toJSON = function toJSON(toJSONOptions) {
2494
2552
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
2495
2553
  return util.toObject([
2554
+ "edition" , this._editionToJSON(),
2496
2555
  "rule" , this.rule !== "optional" && this.rule || undefined,
2497
2556
  "type" , this.type,
2498
2557
  "id" , this.id,
@@ -2532,7 +2591,7 @@ Field.prototype.resolve = function resolve() {
2532
2591
 
2533
2592
  // remove unnecessary options
2534
2593
  if (this.options) {
2535
- if (this.options.packed === true || this.options.packed !== undefined && this.resolvedType && !(this.resolvedType instanceof Enum))
2594
+ if (this.options.packed !== undefined && this.resolvedType && !(this.resolvedType instanceof Enum))
2536
2595
  delete this.options.packed;
2537
2596
  if (!Object.keys(this.options).length)
2538
2597
  this.options = undefined;
@@ -2570,6 +2629,40 @@ Field.prototype.resolve = function resolve() {
2570
2629
  return ReflectionObject.prototype.resolve.call(this);
2571
2630
  };
2572
2631
 
2632
+ /**
2633
+ * Infers field features from legacy syntax that may have been specified differently.
2634
+ * in older editions.
2635
+ * @param {string|undefined} edition The edition this proto is on, or undefined if pre-editions
2636
+ * @returns {object} The feature values to override
2637
+ */
2638
+ Field.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(edition) {
2639
+ if (edition !== "proto2" && edition !== "proto3") {
2640
+ return {};
2641
+ }
2642
+
2643
+ var features = {};
2644
+ this.resolve();
2645
+ if (this.rule === "required") {
2646
+ features.field_presence = "LEGACY_REQUIRED";
2647
+ }
2648
+ if (this.resolvedType instanceof Type && this.resolvedType.group) {
2649
+ features.message_encoding = "DELIMITED";
2650
+ }
2651
+ if (this.getOption("packed") === true) {
2652
+ features.repeated_field_encoding = "PACKED";
2653
+ } else if (this.getOption("packed") === false) {
2654
+ features.repeated_field_encoding = "EXPANDED";
2655
+ }
2656
+ return features;
2657
+ };
2658
+
2659
+ /**
2660
+ * @override
2661
+ */
2662
+ Field.prototype._resolveFeatures = function _resolveFeatures(edition) {
2663
+ return ReflectionObject.prototype._resolveFeatures.call(this, this._edition || edition);
2664
+ };
2665
+
2573
2666
  /**
2574
2667
  * Decorator function as returned by {@link Field.d} and {@link MapField.d} (TypeScript).
2575
2668
  * @typedef FieldDecorator
@@ -3455,6 +3548,15 @@ Namespace.prototype.add = function add(object) {
3455
3548
  }
3456
3549
  }
3457
3550
  this.nested[object.name] = object;
3551
+
3552
+ if (!(this instanceof Type || this instanceof Service || this instanceof Enum || this instanceof Field)) {
3553
+ // This is a package or a root namespace.
3554
+ if (!object._edition) {
3555
+ // Make sure that some edition is set if it hasn't already been specified.
3556
+ object._edition = object._defaultEdition;
3557
+ }
3558
+ }
3559
+
3458
3560
  object.onAdd(this);
3459
3561
  return clearCache(this);
3460
3562
  };
@@ -3517,12 +3619,26 @@ Namespace.prototype.define = function define(path, json) {
3517
3619
  */
3518
3620
  Namespace.prototype.resolveAll = function resolveAll() {
3519
3621
  var nested = this.nestedArray, i = 0;
3622
+ this.resolve();
3520
3623
  while (i < nested.length)
3521
3624
  if (nested[i] instanceof Namespace)
3522
3625
  nested[i++].resolveAll();
3523
3626
  else
3524
3627
  nested[i++].resolve();
3525
- return this.resolve();
3628
+ return this;
3629
+ };
3630
+
3631
+ /**
3632
+ * @override
3633
+ */
3634
+ Namespace.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
3635
+ edition = this._edition || edition;
3636
+
3637
+ ReflectionObject.prototype._resolveFeaturesRecursive.call(this, edition);
3638
+ this.nestedArray.forEach(nested => {
3639
+ nested._resolveFeaturesRecursive(edition);
3640
+ });
3641
+ return this;
3526
3642
  };
3527
3643
 
3528
3644
  /**
@@ -3653,10 +3769,17 @@ module.exports = ReflectionObject;
3653
3769
 
3654
3770
  ReflectionObject.className = "ReflectionObject";
3655
3771
 
3772
+ const OneOf = require(25);
3656
3773
  var util = require(37);
3657
3774
 
3658
3775
  var Root; // cyclic
3659
3776
 
3777
+ /* eslint-disable no-warning-comments */
3778
+ // TODO: Replace with embedded proto.
3779
+ var editions2023Defaults = {enum_type: "OPEN", field_presence: "EXPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY"};
3780
+ var proto2Defaults = {enum_type: "CLOSED", field_presence: "EXPLICIT", json_format: "LEGACY_BEST_EFFORT", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "EXPANDED", utf8_validation: "NONE"};
3781
+ var proto3Defaults = {enum_type: "OPEN", field_presence: "IMPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY"};
3782
+
3660
3783
  /**
3661
3784
  * Constructs a new reflection object instance.
3662
3785
  * @classdesc Base class of all reflection objects.
@@ -3691,6 +3814,25 @@ function ReflectionObject(name, options) {
3691
3814
  */
3692
3815
  this.name = name;
3693
3816
 
3817
+ /**
3818
+ * The edition specified for this object. Only relevant for top-level objects.
3819
+ * @type {string}
3820
+ */
3821
+ this._edition = null;
3822
+
3823
+ /**
3824
+ * The default edition to use for this object if none is specified. For legacy reasons,
3825
+ * this is proto2 except in the JSON parsing case where it was proto3.
3826
+ * @type {string}
3827
+ */
3828
+ this._defaultEdition = "proto2";
3829
+
3830
+ /**
3831
+ * Resolved Features.
3832
+ * @type {object}
3833
+ */
3834
+ this._features = {};
3835
+
3694
3836
  /**
3695
3837
  * Parent namespace.
3696
3838
  * @type {Namespace|null}
@@ -3796,11 +3938,84 @@ ReflectionObject.prototype.onRemove = function onRemove(parent) {
3796
3938
  ReflectionObject.prototype.resolve = function resolve() {
3797
3939
  if (this.resolved)
3798
3940
  return this;
3799
- if (this.root instanceof Root)
3800
- this.resolved = true; // only if part of a root
3941
+ if (this instanceof Root) {
3942
+ this._resolveFeaturesRecursive(this._edition);
3943
+ this.resolved = true;
3944
+ }
3801
3945
  return this;
3802
3946
  };
3803
3947
 
3948
+ /**
3949
+ * Resolves this objects editions features.
3950
+ * @param {string} edition The edition we're currently resolving for.
3951
+ * @returns {ReflectionObject} `this`
3952
+ */
3953
+ ReflectionObject.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
3954
+ return this._resolveFeatures(this._edition || edition);
3955
+ };
3956
+
3957
+ /**
3958
+ * Resolves child features from parent features
3959
+ * @param {string} edition The edition we're currently resolving for.
3960
+ * @returns {undefined}
3961
+ */
3962
+ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition) {
3963
+ var defaults = {};
3964
+
3965
+ /* istanbul ignore if */
3966
+ if (!edition) {
3967
+ throw new Error("Unknown edition for " + this.fullName);
3968
+ }
3969
+
3970
+ var protoFeatures = Object.assign(this.options ? Object.assign({}, this.options.features) : {},
3971
+ this._inferLegacyProtoFeatures(edition));
3972
+
3973
+ if (this._edition) {
3974
+ // For a namespace marked with a specific edition, reset defaults.
3975
+ /* istanbul ignore else */
3976
+ if (edition === "proto2") {
3977
+ defaults = Object.assign({}, proto2Defaults);
3978
+ } else if (edition === "proto3") {
3979
+ defaults = Object.assign({}, proto3Defaults);
3980
+ } else if (edition === "2023") {
3981
+ defaults = Object.assign({}, editions2023Defaults);
3982
+ } else {
3983
+ throw new Error("Unknown edition: " + edition);
3984
+ }
3985
+ this._features = Object.assign(defaults, protoFeatures || {});
3986
+ return;
3987
+ }
3988
+
3989
+ // fields in Oneofs aren't actually children of them, so we have to
3990
+ // special-case it
3991
+ /* istanbul ignore else */
3992
+ if (this.partOf instanceof OneOf) {
3993
+ var lexicalParentFeaturesCopy = Object.assign({}, this.partOf._features);
3994
+ this._features = Object.assign(lexicalParentFeaturesCopy, protoFeatures || {});
3995
+ } else if (this.declaringField) {
3996
+ // Skip feature resolution of sister fields.
3997
+ } else if (this.parent) {
3998
+ var parentFeaturesCopy = Object.assign({}, this.parent._features);
3999
+ this._features = Object.assign(parentFeaturesCopy, protoFeatures || {});
4000
+ } else {
4001
+ throw new Error("Unable to find a parent for " + this.fullName);
4002
+ }
4003
+ if (this.extensionField) {
4004
+ // Sister fields should have the same features as their extensions.
4005
+ this.extensionField._features = this._features;
4006
+ }
4007
+ };
4008
+
4009
+ /**
4010
+ * Infers features from legacy syntax that may have been specified differently.
4011
+ * in older editions.
4012
+ * @param {string|undefined} edition The edition this proto is on, or undefined if pre-editions
4013
+ * @returns {object} The feature values to override
4014
+ */
4015
+ ReflectionObject.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(/*edition*/) {
4016
+ return {};
4017
+ };
4018
+
3804
4019
  /**
3805
4020
  * Gets an option value.
3806
4021
  * @param {string} name Option name
@@ -3816,12 +4031,19 @@ ReflectionObject.prototype.getOption = function getOption(name) {
3816
4031
  * Sets an option.
3817
4032
  * @param {string} name Option name
3818
4033
  * @param {*} value Option value
3819
- * @param {boolean} [ifNotSet] Sets the option only if it isn't currently set
4034
+ * @param {boolean|undefined} [ifNotSet] Sets the option only if it isn't currently set
3820
4035
  * @returns {ReflectionObject} `this`
3821
4036
  */
3822
4037
  ReflectionObject.prototype.setOption = function setOption(name, value, ifNotSet) {
3823
- if (!ifNotSet || !this.options || this.options[name] === undefined)
3824
- (this.options || (this.options = {}))[name] = value;
4038
+ if (!this.options)
4039
+ this.options = {};
4040
+ if (/^features\./.test(name)) {
4041
+ util.setProperty(this.options, name, value, ifNotSet);
4042
+ } else if (!ifNotSet || this.options[name] === undefined) {
4043
+ if (this.getOption(name) !== value) this.resolved = false;
4044
+ this.options[name] = value;
4045
+ }
4046
+
3825
4047
  return this;
3826
4048
  };
3827
4049
 
@@ -3845,10 +4067,11 @@ ReflectionObject.prototype.setParsedOption = function setParsedOption(name, valu
3845
4067
  });
3846
4068
  if (opt) {
3847
4069
  // If we found an existing option - just merge the property value
4070
+ // (If it's a feature, will just write over)
3848
4071
  var newValue = opt[name];
3849
4072
  util.setProperty(newValue, propName, value);
3850
4073
  } else {
3851
- // otherwise, create a new option, set it's property and add it to the list
4074
+ // otherwise, create a new option, set its property and add it to the list
3852
4075
  opt = {};
3853
4076
  opt[name] = util.setProperty({}, propName, value);
3854
4077
  parsedOptions.push(opt);
@@ -3859,6 +4082,7 @@ ReflectionObject.prototype.setParsedOption = function setParsedOption(name, valu
3859
4082
  newOpt[name] = value;
3860
4083
  parsedOptions.push(newOpt);
3861
4084
  }
4085
+
3862
4086
  return this;
3863
4087
  };
3864
4088
 
@@ -3887,12 +4111,25 @@ ReflectionObject.prototype.toString = function toString() {
3887
4111
  return className;
3888
4112
  };
3889
4113
 
4114
+ /**
4115
+ * Converts the edition this object is pinned to for JSON format.
4116
+ * @returns {string|undefined} The edition string for JSON representation
4117
+ */
4118
+ ReflectionObject.prototype._editionToJSON = function _editionToJSON() {
4119
+ if (!this._edition || this._edition === "proto3") {
4120
+ // Avoid emitting proto3 since we need to default to it for backwards
4121
+ // compatibility anyway.
4122
+ return undefined;
4123
+ }
4124
+ return this._edition;
4125
+ };
4126
+
3890
4127
  // Sets up cyclic dependencies (called in index-light)
3891
4128
  ReflectionObject._configure = function(Root_) {
3892
4129
  Root = Root_;
3893
4130
  };
3894
4131
 
3895
- },{"37":37}],25:[function(require,module,exports){
4132
+ },{"25":25,"37":37}],25:[function(require,module,exports){
3896
4133
  "use strict";
3897
4134
  module.exports = OneOf;
3898
4135
 
@@ -4066,6 +4303,25 @@ OneOf.prototype.onRemove = function onRemove(parent) {
4066
4303
  ReflectionObject.prototype.onRemove.call(this, parent);
4067
4304
  };
4068
4305
 
4306
+ /**
4307
+ * Determines whether this field corresponds to a synthetic oneof created for
4308
+ * a proto3 optional field. No behavioral logic should depend on this, but it
4309
+ * can be relevant for reflection.
4310
+ * @name OneOf#isProto3Optional
4311
+ * @type {boolean}
4312
+ * @readonly
4313
+ */
4314
+ Object.defineProperty(OneOf.prototype, "isProto3Optional", {
4315
+ get: function() {
4316
+ if (this.fieldsArray == null || this.fieldsArray.length !== 1) {
4317
+ return false;
4318
+ }
4319
+
4320
+ var field = this.fieldsArray[0];
4321
+ return field.options != null && field.options["proto3_optional"] === true;
4322
+ }
4323
+ });
4324
+
4069
4325
  /**
4070
4326
  * Decorator function as returned by {@link OneOf.d} (TypeScript).
4071
4327
  * @typedef OneOfDecorator
@@ -4113,6 +4369,7 @@ var tokenize = require(34),
4113
4369
  Enum = require(15),
4114
4370
  Service = require(33),
4115
4371
  Method = require(22),
4372
+ ReflectionObject = require(24),
4116
4373
  types = require(36),
4117
4374
  util = require(37);
4118
4375
 
@@ -4124,8 +4381,7 @@ var base10Re = /^[1-9][0-9]*$/,
4124
4381
  base8NegRe = /^-?0[0-7]+$/,
4125
4382
  numberRe = /^(?![eE])[0-9]*(?:\.[0-9]*)?(?:[eE][+-]?[0-9]+)?$/,
4126
4383
  nameRe = /^[a-zA-Z_][a-zA-Z_0-9]*$/,
4127
- typeRefRe = /^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*$/,
4128
- fqTypeRefRe = /^(?:\.[a-zA-Z_][a-zA-Z_0-9]*)+$/;
4384
+ typeRefRe = /^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*$/;
4129
4385
 
4130
4386
  /**
4131
4387
  * Result object returned from {@link parse}.
@@ -4133,7 +4389,6 @@ var base10Re = /^[1-9][0-9]*$/,
4133
4389
  * @property {string|undefined} package Package name, if declared
4134
4390
  * @property {string[]|undefined} imports Imports, if any
4135
4391
  * @property {string[]|undefined} weakImports Weak imports, if any
4136
- * @property {string|undefined} syntax Syntax, if specified (either `"proto2"` or `"proto3"`)
4137
4392
  * @property {Root} root Populated root instance
4138
4393
  */
4139
4394
 
@@ -4181,13 +4436,25 @@ function parse(source, root, options) {
4181
4436
  pkg,
4182
4437
  imports,
4183
4438
  weakImports,
4184
- syntax,
4185
- isProto3 = false;
4439
+ edition = "proto2";
4186
4440
 
4187
4441
  var ptr = root;
4188
4442
 
4443
+ var topLevelObjects = [];
4444
+ var topLevelOptions = {};
4445
+
4189
4446
  var applyCase = options.keepCase ? function(name) { return name; } : util.camelCase;
4190
4447
 
4448
+ function resolveFileFeatures() {
4449
+ topLevelObjects.forEach(obj => {
4450
+ obj._edition = edition;
4451
+ Object.keys(topLevelOptions).forEach(opt => {
4452
+ if (obj.getOption(opt) !== undefined) return;
4453
+ obj.setOption(opt, topLevelOptions[opt], true);
4454
+ });
4455
+ });
4456
+ }
4457
+
4191
4458
  /* istanbul ignore next */
4192
4459
  function illegal(token, name, insideTryCatch) {
4193
4460
  var filename = parse.filename;
@@ -4226,7 +4493,6 @@ function parse(source, root, options) {
4226
4493
  try {
4227
4494
  return parseNumber(token, /* insideTryCatch */ true);
4228
4495
  } catch (e) {
4229
-
4230
4496
  /* istanbul ignore else */
4231
4497
  if (acceptTypeRef && typeRefRe.test(token))
4232
4498
  return token;
@@ -4239,10 +4505,23 @@ function parse(source, root, options) {
4239
4505
  function readRanges(target, acceptStrings) {
4240
4506
  var token, start;
4241
4507
  do {
4242
- if (acceptStrings && ((token = peek()) === "\"" || token === "'"))
4243
- target.push(readString());
4244
- else
4245
- target.push([ start = parseId(next()), skip("to", true) ? parseId(next()) : start ]);
4508
+ if (acceptStrings && ((token = peek()) === "\"" || token === "'")) {
4509
+ var str = readString();
4510
+ target.push(str);
4511
+ if (edition >= 2023) {
4512
+ throw illegal(str, "id");
4513
+ }
4514
+ } else {
4515
+ try {
4516
+ target.push([ start = parseId(next()), skip("to", true) ? parseId(next()) : start ]);
4517
+ } catch (err) {
4518
+ if (acceptStrings && typeRefRe.test(token) && edition >= 2023) {
4519
+ target.push(token);
4520
+ } else {
4521
+ throw err;
4522
+ }
4523
+ }
4524
+ }
4246
4525
  } while (skip(",", true));
4247
4526
  var dummy = {options: undefined};
4248
4527
  dummy.setOption = function(name, value) {
@@ -4319,7 +4598,6 @@ function parse(source, root, options) {
4319
4598
  }
4320
4599
 
4321
4600
  function parsePackage() {
4322
-
4323
4601
  /* istanbul ignore if */
4324
4602
  if (pkg !== undefined)
4325
4603
  throw illegal("package");
@@ -4331,6 +4609,7 @@ function parse(source, root, options) {
4331
4609
  throw illegal(pkg, "name");
4332
4610
 
4333
4611
  ptr = ptr.define(pkg);
4612
+
4334
4613
  skip(";");
4335
4614
  }
4336
4615
 
@@ -4356,20 +4635,28 @@ function parse(source, root, options) {
4356
4635
 
4357
4636
  function parseSyntax() {
4358
4637
  skip("=");
4359
- syntax = readString();
4360
- isProto3 = syntax === "proto3";
4638
+ edition = readString();
4361
4639
 
4362
4640
  /* istanbul ignore if */
4363
- if (!isProto3 && syntax !== "proto2")
4364
- throw illegal(syntax, "syntax");
4641
+ if (edition < 2023)
4642
+ throw illegal(edition, "syntax");
4643
+
4644
+ skip(";");
4645
+ }
4646
+
4647
+ function parseEdition() {
4648
+ skip("=");
4649
+ edition = readString();
4650
+ const supportedEditions = ["2023"];
4365
4651
 
4366
- // Syntax is needed to understand the meaning of the optional field rule
4367
- // Otherwise the meaning is ambiguous between proto2 and proto3
4368
- root.setOption("syntax", syntax);
4652
+ /* istanbul ignore if */
4653
+ if (!supportedEditions.includes(edition))
4654
+ throw illegal(edition, "edition");
4369
4655
 
4370
4656
  skip(";");
4371
4657
  }
4372
4658
 
4659
+
4373
4660
  function parseCommon(parent, token) {
4374
4661
  switch (token) {
4375
4662
 
@@ -4437,14 +4724,19 @@ function parse(source, root, options) {
4437
4724
  break;
4438
4725
 
4439
4726
  case "required":
4727
+ if (edition !== "proto2")
4728
+ throw illegal(token);
4729
+ /* eslint-disable no-fallthrough */
4440
4730
  case "repeated":
4441
4731
  parseField(type, token);
4442
4732
  break;
4443
4733
 
4444
4734
  case "optional":
4445
4735
  /* istanbul ignore if */
4446
- if (isProto3) {
4736
+ if (edition === "proto3") {
4447
4737
  parseField(type, "proto3_optional");
4738
+ } else if (edition !== "proto2") {
4739
+ throw illegal(token);
4448
4740
  } else {
4449
4741
  parseField(type, "optional");
4450
4742
  }
@@ -4464,8 +4756,9 @@ function parse(source, root, options) {
4464
4756
 
4465
4757
  default:
4466
4758
  /* istanbul ignore if */
4467
- if (!isProto3 || !typeRefRe.test(token))
4759
+ if (edition === "proto2" || !typeRefRe.test(token)) {
4468
4760
  throw illegal(token);
4761
+ }
4469
4762
 
4470
4763
  push(token);
4471
4764
  parseField(type, "optional");
@@ -4473,6 +4766,9 @@ function parse(source, root, options) {
4473
4766
  }
4474
4767
  });
4475
4768
  parent.add(type);
4769
+ if (parent === ptr) {
4770
+ topLevelObjects.push(type);
4771
+ }
4476
4772
  }
4477
4773
 
4478
4774
  function parseField(parent, rule, extend) {
@@ -4499,6 +4795,7 @@ function parse(source, root, options) {
4499
4795
  var name = next();
4500
4796
 
4501
4797
  /* istanbul ignore if */
4798
+
4502
4799
  if (!nameRe.test(name))
4503
4800
  throw illegal(name, "name");
4504
4801
 
@@ -4506,6 +4803,7 @@ function parse(source, root, options) {
4506
4803
  skip("=");
4507
4804
 
4508
4805
  var field = new Field(name, parseId(next()), type, rule, extend);
4806
+
4509
4807
  ifBlock(field, function parseField_block(token) {
4510
4808
 
4511
4809
  /* istanbul ignore else */
@@ -4528,15 +4826,15 @@ function parse(source, root, options) {
4528
4826
  } else {
4529
4827
  parent.add(field);
4530
4828
  }
4531
-
4532
- // JSON defaults to packed=true if not set so we have to set packed=false explicity when
4533
- // parsing proto2 descriptors without the option, where applicable. This must be done for
4534
- // all known packable types and anything that could be an enum (= is not a basic type).
4535
- if (!isProto3 && field.repeated && (types.packed[type] !== undefined || types.basic[type] === undefined))
4536
- field.setOption("packed", false, /* ifNotSet */ true);
4829
+ if (parent === ptr) {
4830
+ topLevelObjects.push(field);
4831
+ }
4537
4832
  }
4538
4833
 
4539
4834
  function parseGroup(parent, rule) {
4835
+ if (edition >= 2023) {
4836
+ throw illegal("group");
4837
+ }
4540
4838
  var name = next();
4541
4839
 
4542
4840
  /* istanbul ignore if */
@@ -4559,7 +4857,6 @@ function parse(source, root, options) {
4559
4857
  parseOption(type, token);
4560
4858
  skip(";");
4561
4859
  break;
4562
-
4563
4860
  case "required":
4564
4861
  case "repeated":
4565
4862
  parseField(type, token);
@@ -4567,7 +4864,7 @@ function parse(source, root, options) {
4567
4864
 
4568
4865
  case "optional":
4569
4866
  /* istanbul ignore if */
4570
- if (isProto3) {
4867
+ if (edition === "proto3") {
4571
4868
  parseField(type, "proto3_optional");
4572
4869
  } else {
4573
4870
  parseField(type, "optional");
@@ -4665,6 +4962,7 @@ function parse(source, root, options) {
4665
4962
 
4666
4963
  case "reserved":
4667
4964
  readRanges(enm.reserved || (enm.reserved = []), true);
4965
+ if(enm.reserved === undefined) enm.reserved = [];
4668
4966
  break;
4669
4967
 
4670
4968
  default:
@@ -4672,6 +4970,9 @@ function parse(source, root, options) {
4672
4970
  }
4673
4971
  });
4674
4972
  parent.add(enm);
4973
+ if (parent === ptr) {
4974
+ topLevelObjects.push(enm);
4975
+ }
4675
4976
  }
4676
4977
 
4677
4978
  function parseEnumValue(parent, token) {
@@ -4685,10 +4986,14 @@ function parse(source, root, options) {
4685
4986
  dummy = {
4686
4987
  options: undefined
4687
4988
  };
4989
+ dummy.getOption = function(name) {
4990
+ return this.options[name];
4991
+ };
4688
4992
  dummy.setOption = function(name, value) {
4689
- if (this.options === undefined)
4690
- this.options = {};
4691
- this.options[name] = value;
4993
+ ReflectionObject.prototype.setOption.call(dummy, name, value);
4994
+ };
4995
+ dummy.setParsedOption = function() {
4996
+ return undefined;
4692
4997
  };
4693
4998
  ifBlock(dummy, function parseEnumValue_block(token) {
4694
4999
 
@@ -4702,34 +5007,42 @@ function parse(source, root, options) {
4702
5007
  }, function parseEnumValue_line() {
4703
5008
  parseInlineOptions(dummy); // skip
4704
5009
  });
4705
- parent.add(token, value, dummy.comment, dummy.options);
5010
+ parent.add(token, value, dummy.comment, dummy.parsedOptions || dummy.options);
4706
5011
  }
4707
5012
 
4708
5013
  function parseOption(parent, token) {
4709
- var isCustom = skip("(", true);
4710
-
4711
- /* istanbul ignore if */
4712
- if (!typeRefRe.test(token = next()))
4713
- throw illegal(token, "name");
4714
-
4715
- var name = token;
4716
- var option = name;
4717
- var propName;
5014
+ var option;
5015
+ var propName;
5016
+ var isOption = true;
5017
+ if (token === "option") {
5018
+ token = next();
5019
+ }
4718
5020
 
4719
- if (isCustom) {
4720
- skip(")");
4721
- name = "(" + name + ")";
4722
- option = name;
4723
- token = peek();
4724
- if (fqTypeRefRe.test(token)) {
4725
- propName = token.slice(1); //remove '.' before property name
4726
- name += token;
4727
- next();
5021
+ while (token !== "=") {
5022
+ if (token === "(") {
5023
+ var parensValue = next();
5024
+ skip(")");
5025
+ token = "(" + parensValue + ")";
5026
+ }
5027
+ if (isOption) {
5028
+ isOption = false;
5029
+ if (token.includes(".") && !token.includes("(")) {
5030
+ var tokens = token.split(".");
5031
+ option = tokens[0] + ".";
5032
+ token = tokens[1];
5033
+ continue;
5034
+ }
5035
+ option = token;
5036
+ } else {
5037
+ propName = propName ? propName += token : token;
5038
+ }
5039
+ token = next();
4728
5040
  }
4729
- }
4730
- skip("=");
4731
- var optionValue = parseOptionValue(parent, name);
4732
- setParsedOption(parent, option, optionValue, propName);
5041
+ var name = propName ? option.concat(propName) : option;
5042
+ var optionValue = parseOptionValue(parent, name);
5043
+ propName = propName && propName[0] === "." ? propName.slice(1) : propName;
5044
+ option = option && option[option.length - 1] === "." ? option.slice(0, -1) : option;
5045
+ setParsedOption(parent, option, optionValue, propName);
4733
5046
  }
4734
5047
 
4735
5048
  function parseOptionValue(parent, name) {
@@ -4751,12 +5064,12 @@ function parse(source, root, options) {
4751
5064
 
4752
5065
  skip(":", true);
4753
5066
 
4754
- if (peek() === "{")
4755
- value = parseOptionValue(parent, name + "." + token);
4756
- else if (peek() === "[") {
5067
+ if (peek() === "{") {
4757
5068
  // option (my_option) = {
4758
5069
  // repeated_value: [ "foo", "bar" ]
4759
5070
  // };
5071
+ value = parseOptionValue(parent, name + "." + token);
5072
+ } else if (peek() === "[") {
4760
5073
  value = [];
4761
5074
  var lastValue;
4762
5075
  if (skip("[", true)) {
@@ -4796,6 +5109,10 @@ function parse(source, root, options) {
4796
5109
  }
4797
5110
 
4798
5111
  function setOption(parent, name, value) {
5112
+ if (ptr === parent && /^features\./.test(name)) {
5113
+ topLevelOptions[name] = value;
5114
+ return;
5115
+ }
4799
5116
  if (parent.setOption)
4800
5117
  parent.setOption(name, value);
4801
5118
  }
@@ -4823,8 +5140,9 @@ function parse(source, root, options) {
4823
5140
 
4824
5141
  var service = new Service(token);
4825
5142
  ifBlock(service, function parseService_block(token) {
4826
- if (parseCommon(service, token))
5143
+ if (parseCommon(service, token)) {
4827
5144
  return;
5145
+ }
4828
5146
 
4829
5147
  /* istanbul ignore else */
4830
5148
  if (token === "rpc")
@@ -4833,6 +5151,9 @@ function parse(source, root, options) {
4833
5151
  throw illegal(token);
4834
5152
  });
4835
5153
  parent.add(service);
5154
+ if (parent === ptr) {
5155
+ topLevelObjects.push(service);
5156
+ }
4836
5157
  }
4837
5158
 
4838
5159
  function parseMethod(parent, token) {
@@ -4902,7 +5223,7 @@ function parse(source, root, options) {
4902
5223
 
4903
5224
  case "optional":
4904
5225
  /* istanbul ignore if */
4905
- if (isProto3) {
5226
+ if (edition === "proto3") {
4906
5227
  parseField(parent, "proto3_optional", reference);
4907
5228
  } else {
4908
5229
  parseField(parent, "optional", reference);
@@ -4911,7 +5232,7 @@ function parse(source, root, options) {
4911
5232
 
4912
5233
  default:
4913
5234
  /* istanbul ignore if */
4914
- if (!isProto3 || !typeRefRe.test(token))
5235
+ if (edition === "proto2" || !typeRefRe.test(token))
4915
5236
  throw illegal(token);
4916
5237
  push(token);
4917
5238
  parseField(parent, "optional", reference);
@@ -4951,10 +5272,16 @@ function parse(source, root, options) {
4951
5272
  parseSyntax();
4952
5273
  break;
4953
5274
 
4954
- case "option":
5275
+ case "edition":
5276
+ /* istanbul ignore if */
5277
+ if (!head)
5278
+ throw illegal(token);
5279
+ parseEdition();
5280
+ break;
4955
5281
 
5282
+ case "option":
4956
5283
  parseOption(ptr, token);
4957
- skip(";");
5284
+ skip(";", true);
4958
5285
  break;
4959
5286
 
4960
5287
  default:
@@ -4970,12 +5297,13 @@ function parse(source, root, options) {
4970
5297
  }
4971
5298
  }
4972
5299
 
5300
+ resolveFileFeatures();
5301
+
4973
5302
  parse.filename = null;
4974
5303
  return {
4975
5304
  "package" : pkg,
4976
5305
  "imports" : imports,
4977
5306
  weakImports : weakImports,
4978
- syntax : syntax,
4979
5307
  root : root
4980
5308
  };
4981
5309
  }
@@ -4992,7 +5320,7 @@ function parse(source, root, options) {
4992
5320
  * @variation 2
4993
5321
  */
4994
5322
 
4995
- },{"15":15,"16":16,"20":20,"22":22,"25":25,"29":29,"33":33,"34":34,"35":35,"36":36,"37":37}],27:[function(require,module,exports){
5323
+ },{"15":15,"16":16,"20":20,"22":22,"24":24,"25":25,"29":29,"33":33,"34":34,"35":35,"36":36,"37":37}],27:[function(require,module,exports){
4996
5324
  "use strict";
4997
5325
  module.exports = Reader;
4998
5326
 
@@ -5501,11 +5829,14 @@ function Root(options) {
5501
5829
  * @type {string[]}
5502
5830
  */
5503
5831
  this.files = [];
5832
+
5833
+ // Default to proto2 if unspecified.
5834
+ this._edition = "proto2";
5504
5835
  }
5505
5836
 
5506
5837
  /**
5507
5838
  * Loads a namespace descriptor into a root namespace.
5508
- * @param {INamespace} json Nameespace descriptor
5839
+ * @param {INamespace} json Namespace descriptor
5509
5840
  * @param {Root} [root] Root namespace, defaults to create a new one if omitted
5510
5841
  * @returns {Root} Root namespace
5511
5842
  */
@@ -5514,7 +5845,7 @@ Root.fromJSON = function fromJSON(json, root) {
5514
5845
  root = new Root();
5515
5846
  if (json.options)
5516
5847
  root.setOptions(json.options);
5517
- return root.addJSON(json.nested);
5848
+ return root.addJSON(json.nested).resolveAll();
5518
5849
  };
5519
5850
 
5520
5851
  /**
@@ -5554,20 +5885,26 @@ Root.prototype.load = function load(filename, options, callback) {
5554
5885
  options = undefined;
5555
5886
  }
5556
5887
  var self = this;
5557
- if (!callback)
5888
+ if (!callback) {
5558
5889
  return util.asPromise(load, self, filename, options);
5890
+ }
5559
5891
 
5560
5892
  var sync = callback === SYNC; // undocumented
5561
5893
 
5562
5894
  // Finishes loading by calling the callback (exactly once)
5563
5895
  function finish(err, root) {
5564
5896
  /* istanbul ignore if */
5565
- if (!callback)
5897
+ if (!callback) {
5566
5898
  return;
5567
- if (sync)
5899
+ }
5900
+ if (sync) {
5568
5901
  throw err;
5902
+ }
5569
5903
  var cb = callback;
5570
5904
  callback = null;
5905
+ if (root) {
5906
+ root.resolveAll();
5907
+ }
5571
5908
  cb(err, root);
5572
5909
  }
5573
5910
 
@@ -5605,8 +5942,9 @@ Root.prototype.load = function load(filename, options, callback) {
5605
5942
  } catch (err) {
5606
5943
  finish(err);
5607
5944
  }
5608
- if (!sync && !queued)
5945
+ if (!sync && !queued) {
5609
5946
  finish(null, self); // only once anyway
5947
+ }
5610
5948
  }
5611
5949
 
5612
5950
  // Fetches a single file
@@ -5614,15 +5952,16 @@ Root.prototype.load = function load(filename, options, callback) {
5614
5952
  filename = getBundledFileName(filename) || filename;
5615
5953
 
5616
5954
  // Skip if already loaded / attempted
5617
- if (self.files.indexOf(filename) > -1)
5955
+ if (self.files.indexOf(filename) > -1) {
5618
5956
  return;
5957
+ }
5619
5958
  self.files.push(filename);
5620
5959
 
5621
5960
  // Shortcut bundled definitions
5622
5961
  if (filename in common) {
5623
- if (sync)
5962
+ if (sync) {
5624
5963
  process(filename, common[filename]);
5625
- else {
5964
+ } else {
5626
5965
  ++queued;
5627
5966
  setTimeout(function() {
5628
5967
  --queued;
@@ -5648,8 +5987,9 @@ Root.prototype.load = function load(filename, options, callback) {
5648
5987
  self.fetch(filename, function(err, source) {
5649
5988
  --queued;
5650
5989
  /* istanbul ignore if */
5651
- if (!callback)
5990
+ if (!callback) {
5652
5991
  return; // terminated meanwhile
5992
+ }
5653
5993
  if (err) {
5654
5994
  /* istanbul ignore else */
5655
5995
  if (!weak)
@@ -5666,17 +6006,21 @@ Root.prototype.load = function load(filename, options, callback) {
5666
6006
 
5667
6007
  // Assembling the root namespace doesn't require working type
5668
6008
  // references anymore, so we can load everything in parallel
5669
- if (util.isString(filename))
6009
+ if (util.isString(filename)) {
5670
6010
  filename = [ filename ];
6011
+ }
5671
6012
  for (var i = 0, resolved; i < filename.length; ++i)
5672
6013
  if (resolved = self.resolvePath("", filename[i]))
5673
6014
  fetch(resolved);
5674
-
5675
- if (sync)
6015
+ self.resolveAll();
6016
+ if (sync) {
5676
6017
  return self;
5677
- if (!queued)
6018
+ }
6019
+ if (!queued) {
5678
6020
  finish(null, self);
5679
- return undefined;
6021
+ }
6022
+
6023
+ return self;
5680
6024
  };
5681
6025
  // function load(filename:string, options:IParseOptions, callback:LoadCallback):undefined
5682
6026
 
@@ -6095,7 +6439,10 @@ Service.fromJSON = function fromJSON(name, json) {
6095
6439
  service.add(Method.fromJSON(names[i], json.methods[names[i]]));
6096
6440
  if (json.nested)
6097
6441
  service.addJSON(json.nested);
6442
+ if (json.edition)
6443
+ service._edition = json.edition;
6098
6444
  service.comment = json.comment;
6445
+ service._defaultEdition = "proto3"; // For backwards-compatibility.
6099
6446
  return service;
6100
6447
  };
6101
6448
 
@@ -6108,6 +6455,7 @@ Service.prototype.toJSON = function toJSON(toJSONOptions) {
6108
6455
  var inherited = Namespace.prototype.toJSON.call(this, toJSONOptions);
6109
6456
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
6110
6457
  return util.toObject([
6458
+ "edition" , this._editionToJSON(),
6111
6459
  "options" , inherited && inherited.options || undefined,
6112
6460
  "methods" , Namespace.arrayToJSON(this.methodsArray, toJSONOptions) || /* istanbul ignore next */ {},
6113
6461
  "nested" , inherited && inherited.nested || undefined,
@@ -6144,10 +6492,24 @@ Service.prototype.get = function get(name) {
6144
6492
  * @override
6145
6493
  */
6146
6494
  Service.prototype.resolveAll = function resolveAll() {
6495
+ Namespace.prototype.resolve.call(this);
6147
6496
  var methods = this.methodsArray;
6148
6497
  for (var i = 0; i < methods.length; ++i)
6149
6498
  methods[i].resolve();
6150
- return Namespace.prototype.resolve.call(this);
6499
+ return this;
6500
+ };
6501
+
6502
+ /**
6503
+ * @override
6504
+ */
6505
+ Service.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
6506
+ edition = this._edition || edition;
6507
+
6508
+ Namespace.prototype._resolveFeaturesRecursive.call(this, edition);
6509
+ this.methodsArray.forEach(method => {
6510
+ method._resolveFeaturesRecursive(edition);
6511
+ });
6512
+ return this;
6151
6513
  };
6152
6514
 
6153
6515
  /**
@@ -6897,6 +7259,9 @@ Type.fromJSON = function fromJSON(name, json) {
6897
7259
  type.group = true;
6898
7260
  if (json.comment)
6899
7261
  type.comment = json.comment;
7262
+ if (json.edition)
7263
+ type._edition = json.edition;
7264
+ type._defaultEdition = "proto3"; // For backwards-compatibility.
6900
7265
  return type;
6901
7266
  };
6902
7267
 
@@ -6909,6 +7274,7 @@ Type.prototype.toJSON = function toJSON(toJSONOptions) {
6909
7274
  var inherited = Namespace.prototype.toJSON.call(this, toJSONOptions);
6910
7275
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
6911
7276
  return util.toObject([
7277
+ "edition" , this._editionToJSON(),
6912
7278
  "options" , inherited && inherited.options || undefined,
6913
7279
  "oneofs" , Namespace.arrayToJSON(this.oneofsArray, toJSONOptions),
6914
7280
  "fields" , Namespace.arrayToJSON(this.fieldsArray.filter(function(obj) { return !obj.declaringField; }), toJSONOptions) || {},
@@ -6924,13 +7290,30 @@ Type.prototype.toJSON = function toJSON(toJSONOptions) {
6924
7290
  * @override
6925
7291
  */
6926
7292
  Type.prototype.resolveAll = function resolveAll() {
6927
- var fields = this.fieldsArray, i = 0;
6928
- while (i < fields.length)
6929
- fields[i++].resolve();
7293
+ Namespace.prototype.resolveAll.call(this);
6930
7294
  var oneofs = this.oneofsArray; i = 0;
6931
7295
  while (i < oneofs.length)
6932
7296
  oneofs[i++].resolve();
6933
- return Namespace.prototype.resolveAll.call(this);
7297
+ var fields = this.fieldsArray, i = 0;
7298
+ while (i < fields.length)
7299
+ fields[i++].resolve();
7300
+ return this;
7301
+ };
7302
+
7303
+ /**
7304
+ * @override
7305
+ */
7306
+ Type.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
7307
+ edition = this._edition || edition;
7308
+
7309
+ Namespace.prototype._resolveFeaturesRecursive.call(this, edition);
7310
+ this.oneofsArray.forEach(oneof => {
7311
+ oneof._resolveFeatures(edition);
7312
+ });
7313
+ this.fieldsArray.forEach(field => {
7314
+ field._resolveFeatures(edition);
7315
+ });
7316
+ return this;
6934
7317
  };
6935
7318
 
6936
7319
  /**
@@ -7585,9 +7968,10 @@ util.decorateEnum = function decorateEnum(object) {
7585
7968
  * @param {Object.<string,*>} dst Destination object
7586
7969
  * @param {string} path dot '.' delimited path of the property to set
7587
7970
  * @param {Object} value the value to set
7971
+ * @param {boolean|undefined} [ifNotSet] Sets the option only if it isn't currently set
7588
7972
  * @returns {Object.<string,*>} Destination object
7589
7973
  */
7590
- util.setProperty = function setProperty(dst, path, value) {
7974
+ util.setProperty = function setProperty(dst, path, value, ifNotSet) {
7591
7975
  function setProp(dst, path, value) {
7592
7976
  var part = path.shift();
7593
7977
  if (part === "__proto__" || part === "prototype") {
@@ -7597,6 +7981,8 @@ util.setProperty = function setProperty(dst, path, value) {
7597
7981
  dst[part] = setProp(dst[part] || {}, path, value);
7598
7982
  } else {
7599
7983
  var prevValue = dst[part];
7984
+ if (prevValue && ifNotSet)
7985
+ return dst;
7600
7986
  if (prevValue)
7601
7987
  value = [].concat(prevValue).concat(value);
7602
7988
  dst[part] = value;