protobufjs 7.4.0 → 7.5.1

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.
@@ -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.1 (c) 2016, daniel wirtz
3
+ * compiled thu, 08 may 2025 17:34:56 utc
4
4
  * licensed under the bsd-3-clause license
5
5
  * see: https://github.com/dcodeio/protobuf.js for details
6
6
  */
@@ -1430,16 +1430,14 @@ function missing(field) {
1430
1430
  */
1431
1431
  function decoder(mtype) {
1432
1432
  /* eslint-disable no-unexpected-multiline */
1433
- var gen = util.codegen(["r", "l"], mtype.name + "$decode")
1433
+ var gen = util.codegen(["r", "l", "e"], mtype.name + "$decode")
1434
1434
  ("if(!(r instanceof Reader))")
1435
1435
  ("r=Reader.create(r)")
1436
1436
  ("var c=l===undefined?r.len:r.pos+l,m=new this.ctor" + (mtype.fieldsArray.filter(function(field) { return field.map; }).length ? ",k,value" : ""))
1437
1437
  ("while(r.pos<c){")
1438
- ("var t=r.uint32()");
1439
- if (mtype.group) gen
1440
- ("if((t&7)===4)")
1441
- ("break");
1442
- gen
1438
+ ("var t=r.uint32()")
1439
+ ("if(t===e)")
1440
+ ("break")
1443
1441
  ("switch(t>>>3){");
1444
1442
 
1445
1443
  var i = 0;
@@ -1505,15 +1503,15 @@ function decoder(mtype) {
1505
1503
  ("}else");
1506
1504
 
1507
1505
  // Non-packed
1508
- if (types.basic[type] === undefined) gen(field.resolvedType.group
1509
- ? "%s.push(types[%i].decode(r))"
1506
+ if (types.basic[type] === undefined) gen(field.delimited
1507
+ ? "%s.push(types[%i].decode(r,undefined,((t&~7)|4)))"
1510
1508
  : "%s.push(types[%i].decode(r,r.uint32()))", ref, i);
1511
1509
  else gen
1512
1510
  ("%s.push(r.%s())", ref, type);
1513
1511
 
1514
1512
  // Non-repeated
1515
- } else if (types.basic[type] === undefined) gen(field.resolvedType.group
1516
- ? "%s=types[%i].decode(r)"
1513
+ } else if (types.basic[type] === undefined) gen(field.delimited
1514
+ ? "%s=types[%i].decode(r,undefined,((t&~7)|4))"
1517
1515
  : "%s=types[%i].decode(r,r.uint32())", ref, i);
1518
1516
  else gen
1519
1517
  ("%s=r.%s()", ref, type);
@@ -1560,7 +1558,7 @@ var Enum = require(14),
1560
1558
  * @ignore
1561
1559
  */
1562
1560
  function genTypePartial(gen, field, fieldIndex, ref) {
1563
- return field.resolvedType.group
1561
+ return field.delimited
1564
1562
  ? gen("types[%i].encode(%s,w.uint32(%i)).uint32(%i)", fieldIndex, ref, (field.id << 3 | 3) >>> 0, (field.id << 3 | 4) >>> 0)
1565
1563
  : gen("types[%i].encode(%s,w.uint32(%i).fork()).ldelim()", fieldIndex, ref, (field.id << 3 | 2) >>> 0);
1566
1564
  }
@@ -1703,6 +1701,12 @@ function Enum(name, values, options, comment, comments, valuesOptions) {
1703
1701
  */
1704
1702
  this.valuesOptions = valuesOptions;
1705
1703
 
1704
+ /**
1705
+ * Resolved values features, if any
1706
+ * @type {Object<string, Object<string, *>>|undefined}
1707
+ */
1708
+ this._valuesFeatures = {};
1709
+
1706
1710
  /**
1707
1711
  * Reserved ranges, if any.
1708
1712
  * @type {Array.<number[]|string>}
@@ -1719,6 +1723,21 @@ function Enum(name, values, options, comment, comments, valuesOptions) {
1719
1723
  this.valuesById[ this.values[keys[i]] = values[keys[i]] ] = keys[i];
1720
1724
  }
1721
1725
 
1726
+ /**
1727
+ * @override
1728
+ */
1729
+ Enum.prototype._resolveFeatures = function _resolveFeatures(edition) {
1730
+ edition = this._edition || edition;
1731
+ ReflectionObject.prototype._resolveFeatures.call(this, edition);
1732
+
1733
+ Object.keys(this.values).forEach(key => {
1734
+ var parentFeaturesCopy = Object.assign({}, this._features);
1735
+ this._valuesFeatures[key] = Object.assign(parentFeaturesCopy, this.valuesOptions && this.valuesOptions[key] && this.valuesOptions[key].features);
1736
+ });
1737
+
1738
+ return this;
1739
+ };
1740
+
1722
1741
  /**
1723
1742
  * Enum descriptor.
1724
1743
  * @interface IEnum
@@ -1736,6 +1755,9 @@ function Enum(name, values, options, comment, comments, valuesOptions) {
1736
1755
  Enum.fromJSON = function fromJSON(name, json) {
1737
1756
  var enm = new Enum(name, json.values, json.options, json.comment, json.comments);
1738
1757
  enm.reserved = json.reserved;
1758
+ if (json.edition)
1759
+ enm._edition = json.edition;
1760
+ enm._defaultEdition = "proto3"; // For backwards-compatibility.
1739
1761
  return enm;
1740
1762
  };
1741
1763
 
@@ -1747,6 +1769,7 @@ Enum.fromJSON = function fromJSON(name, json) {
1747
1769
  Enum.prototype.toJSON = function toJSON(toJSONOptions) {
1748
1770
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
1749
1771
  return util.toObject([
1772
+ "edition" , this._editionToJSON(),
1750
1773
  "options" , this.options,
1751
1774
  "valuesOptions" , this.valuesOptions,
1752
1775
  "values" , this.values,
@@ -1882,7 +1905,11 @@ var ruleRe = /^required|optional|repeated$/;
1882
1905
  * @throws {TypeError} If arguments are invalid
1883
1906
  */
1884
1907
  Field.fromJSON = function fromJSON(name, json) {
1885
- return new Field(name, json.id, json.type, json.rule, json.extend, json.options, json.comment);
1908
+ var field = new Field(name, json.id, json.type, json.rule, json.extend, json.options, json.comment);
1909
+ if (json.edition)
1910
+ field._edition = json.edition;
1911
+ field._defaultEdition = "proto3"; // For backwards-compatibility.
1912
+ return field;
1886
1913
  };
1887
1914
 
1888
1915
  /**
@@ -1952,18 +1979,6 @@ function Field(name, id, type, rule, extend, options, comment) {
1952
1979
  */
1953
1980
  this.extend = extend || undefined; // toJSON
1954
1981
 
1955
- /**
1956
- * Whether this field is required.
1957
- * @type {boolean}
1958
- */
1959
- this.required = rule === "required";
1960
-
1961
- /**
1962
- * Whether this field is optional.
1963
- * @type {boolean}
1964
- */
1965
- this.optional = !this.required;
1966
-
1967
1982
  /**
1968
1983
  * Whether this field is repeated.
1969
1984
  * @type {boolean}
@@ -2030,13 +2045,6 @@ function Field(name, id, type, rule, extend, options, comment) {
2030
2045
  */
2031
2046
  this.declaringField = null;
2032
2047
 
2033
- /**
2034
- * Internally remembers whether this field is packed.
2035
- * @type {boolean|null}
2036
- * @private
2037
- */
2038
- this._packed = null;
2039
-
2040
2048
  /**
2041
2049
  * Comment for this field.
2042
2050
  * @type {string|null}
@@ -2045,17 +2053,69 @@ function Field(name, id, type, rule, extend, options, comment) {
2045
2053
  }
2046
2054
 
2047
2055
  /**
2048
- * Determines whether this field is packed. Only relevant when repeated and working with proto2.
2056
+ * Determines whether this field is required.
2057
+ * @name Field#required
2058
+ * @type {boolean}
2059
+ * @readonly
2060
+ */
2061
+ Object.defineProperty(Field.prototype, "required", {
2062
+ get: function() {
2063
+ return this._features.field_presence === "LEGACY_REQUIRED";
2064
+ }
2065
+ });
2066
+
2067
+ /**
2068
+ * Determines whether this field is not required.
2069
+ * @name Field#optional
2070
+ * @type {boolean}
2071
+ * @readonly
2072
+ */
2073
+ Object.defineProperty(Field.prototype, "optional", {
2074
+ get: function() {
2075
+ return !this.required;
2076
+ }
2077
+ });
2078
+
2079
+ /**
2080
+ * Determines whether this field uses tag-delimited encoding. In proto2 this
2081
+ * corresponded to group syntax.
2082
+ * @name Field#delimited
2083
+ * @type {boolean}
2084
+ * @readonly
2085
+ */
2086
+ Object.defineProperty(Field.prototype, "delimited", {
2087
+ get: function() {
2088
+ return this.resolvedType instanceof Type &&
2089
+ this._features.message_encoding === "DELIMITED";
2090
+ }
2091
+ });
2092
+
2093
+ /**
2094
+ * Determines whether this field is packed. Only relevant when repeated.
2049
2095
  * @name Field#packed
2050
2096
  * @type {boolean}
2051
2097
  * @readonly
2052
2098
  */
2053
2099
  Object.defineProperty(Field.prototype, "packed", {
2054
2100
  get: function() {
2055
- // defaults to packed=true if not explicity set to false
2056
- if (this._packed === null)
2057
- this._packed = this.getOption("packed") !== false;
2058
- return this._packed;
2101
+ return this._features.repeated_field_encoding === "PACKED";
2102
+ }
2103
+ });
2104
+
2105
+ /**
2106
+ * Determines whether this field tracks presence.
2107
+ * @name Field#hasPresence
2108
+ * @type {boolean}
2109
+ * @readonly
2110
+ */
2111
+ Object.defineProperty(Field.prototype, "hasPresence", {
2112
+ get: function() {
2113
+ if (this.repeated || this.map) {
2114
+ return false;
2115
+ }
2116
+ return this.partOf || // oneofs
2117
+ this.declaringField || this.extensionField || // extensions
2118
+ this._features.field_presence !== "IMPLICIT";
2059
2119
  }
2060
2120
  });
2061
2121
 
@@ -2063,8 +2123,6 @@ Object.defineProperty(Field.prototype, "packed", {
2063
2123
  * @override
2064
2124
  */
2065
2125
  Field.prototype.setOption = function setOption(name, value, ifNotSet) {
2066
- if (name === "packed") // clear cached before setting
2067
- this._packed = null;
2068
2126
  return ReflectionObject.prototype.setOption.call(this, name, value, ifNotSet);
2069
2127
  };
2070
2128
 
@@ -2092,6 +2150,7 @@ Field.prototype.setOption = function setOption(name, value, ifNotSet) {
2092
2150
  Field.prototype.toJSON = function toJSON(toJSONOptions) {
2093
2151
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
2094
2152
  return util.toObject([
2153
+ "edition" , this._editionToJSON(),
2095
2154
  "rule" , this.rule !== "optional" && this.rule || undefined,
2096
2155
  "type" , this.type,
2097
2156
  "id" , this.id,
@@ -2131,7 +2190,7 @@ Field.prototype.resolve = function resolve() {
2131
2190
 
2132
2191
  // remove unnecessary options
2133
2192
  if (this.options) {
2134
- if (this.options.packed === true || this.options.packed !== undefined && this.resolvedType && !(this.resolvedType instanceof Enum))
2193
+ if (this.options.packed !== undefined && this.resolvedType && !(this.resolvedType instanceof Enum))
2135
2194
  delete this.options.packed;
2136
2195
  if (!Object.keys(this.options).length)
2137
2196
  this.options = undefined;
@@ -2169,6 +2228,46 @@ Field.prototype.resolve = function resolve() {
2169
2228
  return ReflectionObject.prototype.resolve.call(this);
2170
2229
  };
2171
2230
 
2231
+ /**
2232
+ * Infers field features from legacy syntax that may have been specified differently.
2233
+ * in older editions.
2234
+ * @param {string|undefined} edition The edition this proto is on, or undefined if pre-editions
2235
+ * @returns {object} The feature values to override
2236
+ */
2237
+ Field.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(edition) {
2238
+ if (edition !== "proto2" && edition !== "proto3") {
2239
+ return {};
2240
+ }
2241
+
2242
+ var features = {};
2243
+
2244
+ if (this.rule === "required") {
2245
+ features.field_presence = "LEGACY_REQUIRED";
2246
+ }
2247
+ if (this.parent && types.defaults[this.type] === undefined) {
2248
+ // We can't use resolvedType because types may not have been resolved yet. However,
2249
+ // legacy groups are always in the same scope as the field so we don't have to do a
2250
+ // full scan of the tree.
2251
+ var type = this.parent.get(this.type.split(".").pop());
2252
+ if (type && type instanceof Type && type.group) {
2253
+ features.message_encoding = "DELIMITED";
2254
+ }
2255
+ }
2256
+ if (this.getOption("packed") === true) {
2257
+ features.repeated_field_encoding = "PACKED";
2258
+ } else if (this.getOption("packed") === false) {
2259
+ features.repeated_field_encoding = "EXPANDED";
2260
+ }
2261
+ return features;
2262
+ };
2263
+
2264
+ /**
2265
+ * @override
2266
+ */
2267
+ Field.prototype._resolveFeatures = function _resolveFeatures(edition) {
2268
+ return ReflectionObject.prototype._resolveFeatures.call(this, this._edition || edition);
2269
+ };
2270
+
2172
2271
  /**
2173
2272
  * Decorator function as returned by {@link Field.d} and {@link MapField.d} (TypeScript).
2174
2273
  * @typedef FieldDecorator
@@ -2908,10 +3007,33 @@ function Namespace(name, options) {
2908
3007
  * @private
2909
3008
  */
2910
3009
  this._nestedArray = null;
3010
+
3011
+ /**
3012
+ * Cache lookup calls for any objects contains anywhere under this namespace.
3013
+ * This drastically speeds up resolve for large cross-linked protos where the same
3014
+ * types are looked up repeatedly.
3015
+ * @type {Object.<string,ReflectionObject|null>}
3016
+ * @private
3017
+ */
3018
+ this._lookupCache = {};
3019
+
3020
+ /**
3021
+ * Whether or not objects contained in this namespace need feature resolution.
3022
+ * @type {boolean}
3023
+ * @protected
3024
+ */
3025
+ this._needsRecursiveFeatureResolution = true;
2911
3026
  }
2912
3027
 
2913
3028
  function clearCache(namespace) {
2914
3029
  namespace._nestedArray = null;
3030
+ namespace._lookupCache = {};
3031
+
3032
+ // Also clear parent caches, since they include nested lookups.
3033
+ var parent = namespace;
3034
+ while(parent = parent.parent) {
3035
+ parent._lookupCache = {};
3036
+ }
2915
3037
  return namespace;
2916
3038
  }
2917
3039
 
@@ -3040,6 +3162,23 @@ Namespace.prototype.add = function add(object) {
3040
3162
  }
3041
3163
  }
3042
3164
  this.nested[object.name] = object;
3165
+
3166
+ if (!(this instanceof Type || this instanceof Service || this instanceof Enum || this instanceof Field)) {
3167
+ // This is a package or a root namespace.
3168
+ if (!object._edition) {
3169
+ // Make sure that some edition is set if it hasn't already been specified.
3170
+ object._edition = object._defaultEdition;
3171
+ }
3172
+ }
3173
+
3174
+ this._needsRecursiveFeatureResolution = true;
3175
+
3176
+ // Also clear parent caches, since they need to recurse down.
3177
+ var parent = this;
3178
+ while(parent = parent.parent) {
3179
+ parent._needsRecursiveFeatureResolution = true;
3180
+ }
3181
+
3043
3182
  object.onAdd(this);
3044
3183
  return clearCache(this);
3045
3184
  };
@@ -3102,12 +3241,29 @@ Namespace.prototype.define = function define(path, json) {
3102
3241
  */
3103
3242
  Namespace.prototype.resolveAll = function resolveAll() {
3104
3243
  var nested = this.nestedArray, i = 0;
3244
+ this.resolve();
3105
3245
  while (i < nested.length)
3106
3246
  if (nested[i] instanceof Namespace)
3107
3247
  nested[i++].resolveAll();
3108
3248
  else
3109
3249
  nested[i++].resolve();
3110
- return this.resolve();
3250
+ return this;
3251
+ };
3252
+
3253
+ /**
3254
+ * @override
3255
+ */
3256
+ Namespace.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
3257
+ if (!this._needsRecursiveFeatureResolution) return this;
3258
+ this._needsRecursiveFeatureResolution = false;
3259
+
3260
+ edition = this._edition || edition;
3261
+
3262
+ ReflectionObject.prototype._resolveFeaturesRecursive.call(this, edition);
3263
+ this.nestedArray.forEach(nested => {
3264
+ nested._resolveFeaturesRecursive(edition);
3265
+ });
3266
+ return this;
3111
3267
  };
3112
3268
 
3113
3269
  /**
@@ -3118,7 +3274,6 @@ Namespace.prototype.resolveAll = function resolveAll() {
3118
3274
  * @returns {ReflectionObject|null} Looked up object or `null` if none could be found
3119
3275
  */
3120
3276
  Namespace.prototype.lookup = function lookup(path, filterTypes, parentAlreadyChecked) {
3121
-
3122
3277
  /* istanbul ignore next */
3123
3278
  if (typeof filterTypes === "boolean") {
3124
3279
  parentAlreadyChecked = filterTypes;
@@ -3137,25 +3292,48 @@ Namespace.prototype.lookup = function lookup(path, filterTypes, parentAlreadyChe
3137
3292
  if (path[0] === "")
3138
3293
  return this.root.lookup(path.slice(1), filterTypes);
3139
3294
 
3295
+ var found = this._lookupImpl(path);
3296
+ if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) {
3297
+ return found;
3298
+ }
3299
+
3300
+ // If there hasn't been a match, try again at the parent
3301
+ if (this.parent === null || parentAlreadyChecked)
3302
+ return null;
3303
+ return this.parent.lookup(path, filterTypes);
3304
+ };
3305
+
3306
+ /**
3307
+ * Internal helper for lookup that handles searching just at this namespace and below along with caching.
3308
+ * @param {string[]} path Path to look up
3309
+ * @returns {ReflectionObject|null} Looked up object or `null` if none could be found
3310
+ * @private
3311
+ */
3312
+ Namespace.prototype._lookupImpl = function lookup(path) {
3313
+ var flatPath = path.join(".");
3314
+ if(Object.prototype.hasOwnProperty.call(this._lookupCache, flatPath)) {
3315
+ return this._lookupCache[flatPath];
3316
+ }
3317
+
3140
3318
  // Test if the first part matches any nested object, and if so, traverse if path contains more
3141
3319
  var found = this.get(path[0]);
3320
+ var exact = null;
3142
3321
  if (found) {
3143
3322
  if (path.length === 1) {
3144
- if (!filterTypes || filterTypes.indexOf(found.constructor) > -1)
3145
- return found;
3146
- } else if (found instanceof Namespace && (found = found.lookup(path.slice(1), filterTypes, true)))
3147
- return found;
3323
+ exact = found;
3324
+ } else if (found instanceof Namespace && (found = found._lookupImpl(path.slice(1))))
3325
+ exact = found;
3148
3326
 
3149
3327
  // Otherwise try each nested namespace
3150
- } else
3328
+ } else {
3151
3329
  for (var i = 0; i < this.nestedArray.length; ++i)
3152
- if (this._nestedArray[i] instanceof Namespace && (found = this._nestedArray[i].lookup(path, filterTypes, true)))
3153
- return found;
3330
+ if (this._nestedArray[i] instanceof Namespace && (found = this._nestedArray[i]._lookupImpl(path)))
3331
+ exact = found;
3332
+ }
3154
3333
 
3155
- // If there hasn't been a match, try again at the parent
3156
- if (this.parent === null || parentAlreadyChecked)
3157
- return null;
3158
- return this.parent.lookup(path, filterTypes);
3334
+ // Set this even when null, so that when we walk up the tree we can quickly bail on repeated checks back down.
3335
+ this._lookupCache[flatPath] = exact;
3336
+ return exact;
3159
3337
  };
3160
3338
 
3161
3339
  /**
@@ -3238,10 +3416,17 @@ module.exports = ReflectionObject;
3238
3416
 
3239
3417
  ReflectionObject.className = "ReflectionObject";
3240
3418
 
3419
+ const OneOf = require(23);
3241
3420
  var util = require(33);
3242
3421
 
3243
3422
  var Root; // cyclic
3244
3423
 
3424
+ /* eslint-disable no-warning-comments */
3425
+ // TODO: Replace with embedded proto.
3426
+ var editions2023Defaults = {enum_type: "OPEN", field_presence: "EXPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY"};
3427
+ var proto2Defaults = {enum_type: "CLOSED", field_presence: "EXPLICIT", json_format: "LEGACY_BEST_EFFORT", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "EXPANDED", utf8_validation: "NONE"};
3428
+ var proto3Defaults = {enum_type: "OPEN", field_presence: "IMPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY"};
3429
+
3245
3430
  /**
3246
3431
  * Constructs a new reflection object instance.
3247
3432
  * @classdesc Base class of all reflection objects.
@@ -3276,6 +3461,31 @@ function ReflectionObject(name, options) {
3276
3461
  */
3277
3462
  this.name = name;
3278
3463
 
3464
+ /**
3465
+ * The edition specified for this object. Only relevant for top-level objects.
3466
+ * @type {string}
3467
+ */
3468
+ this._edition = null;
3469
+
3470
+ /**
3471
+ * The default edition to use for this object if none is specified. For legacy reasons,
3472
+ * this is proto2 except in the JSON parsing case where it was proto3.
3473
+ * @type {string}
3474
+ */
3475
+ this._defaultEdition = "proto2";
3476
+
3477
+ /**
3478
+ * Resolved Features.
3479
+ * @type {object}
3480
+ */
3481
+ this._features = {};
3482
+
3483
+ /**
3484
+ * Whether or not features have been resolved.
3485
+ * @type {boolean}
3486
+ */
3487
+ this._featuresResolved = false;
3488
+
3279
3489
  /**
3280
3490
  * Parent namespace.
3281
3491
  * @type {Namespace|null}
@@ -3386,6 +3596,83 @@ ReflectionObject.prototype.resolve = function resolve() {
3386
3596
  return this;
3387
3597
  };
3388
3598
 
3599
+ /**
3600
+ * Resolves this objects editions features.
3601
+ * @param {string} edition The edition we're currently resolving for.
3602
+ * @returns {ReflectionObject} `this`
3603
+ */
3604
+ ReflectionObject.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
3605
+ return this._resolveFeatures(this._edition || edition);
3606
+ };
3607
+
3608
+ /**
3609
+ * Resolves child features from parent features
3610
+ * @param {string} edition The edition we're currently resolving for.
3611
+ * @returns {undefined}
3612
+ */
3613
+ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition) {
3614
+ if (this._featuresResolved) {
3615
+ return;
3616
+ }
3617
+
3618
+ var defaults = {};
3619
+
3620
+ /* istanbul ignore if */
3621
+ if (!edition) {
3622
+ throw new Error("Unknown edition for " + this.fullName);
3623
+ }
3624
+
3625
+ var protoFeatures = Object.assign(this.options ? Object.assign({}, this.options.features) : {},
3626
+ this._inferLegacyProtoFeatures(edition));
3627
+
3628
+ if (this._edition) {
3629
+ // For a namespace marked with a specific edition, reset defaults.
3630
+ /* istanbul ignore else */
3631
+ if (edition === "proto2") {
3632
+ defaults = Object.assign({}, proto2Defaults);
3633
+ } else if (edition === "proto3") {
3634
+ defaults = Object.assign({}, proto3Defaults);
3635
+ } else if (edition === "2023") {
3636
+ defaults = Object.assign({}, editions2023Defaults);
3637
+ } else {
3638
+ throw new Error("Unknown edition: " + edition);
3639
+ }
3640
+ this._features = Object.assign(defaults, protoFeatures || {});
3641
+ this._featuresResolved = true;
3642
+ return;
3643
+ }
3644
+
3645
+ // fields in Oneofs aren't actually children of them, so we have to
3646
+ // special-case it
3647
+ /* istanbul ignore else */
3648
+ if (this.partOf instanceof OneOf) {
3649
+ var lexicalParentFeaturesCopy = Object.assign({}, this.partOf._features);
3650
+ this._features = Object.assign(lexicalParentFeaturesCopy, protoFeatures || {});
3651
+ } else if (this.declaringField) {
3652
+ // Skip feature resolution of sister fields.
3653
+ } else if (this.parent) {
3654
+ var parentFeaturesCopy = Object.assign({}, this.parent._features);
3655
+ this._features = Object.assign(parentFeaturesCopy, protoFeatures || {});
3656
+ } else {
3657
+ throw new Error("Unable to find a parent for " + this.fullName);
3658
+ }
3659
+ if (this.extensionField) {
3660
+ // Sister fields should have the same features as their extensions.
3661
+ this.extensionField._features = this._features;
3662
+ }
3663
+ this._featuresResolved = true;
3664
+ };
3665
+
3666
+ /**
3667
+ * Infers features from legacy syntax that may have been specified differently.
3668
+ * in older editions.
3669
+ * @param {string|undefined} edition The edition this proto is on, or undefined if pre-editions
3670
+ * @returns {object} The feature values to override
3671
+ */
3672
+ ReflectionObject.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(/*edition*/) {
3673
+ return {};
3674
+ };
3675
+
3389
3676
  /**
3390
3677
  * Gets an option value.
3391
3678
  * @param {string} name Option name
@@ -3401,12 +3688,19 @@ ReflectionObject.prototype.getOption = function getOption(name) {
3401
3688
  * Sets an option.
3402
3689
  * @param {string} name Option name
3403
3690
  * @param {*} value Option value
3404
- * @param {boolean} [ifNotSet] Sets the option only if it isn't currently set
3691
+ * @param {boolean|undefined} [ifNotSet] Sets the option only if it isn't currently set
3405
3692
  * @returns {ReflectionObject} `this`
3406
3693
  */
3407
3694
  ReflectionObject.prototype.setOption = function setOption(name, value, ifNotSet) {
3408
- if (!ifNotSet || !this.options || this.options[name] === undefined)
3409
- (this.options || (this.options = {}))[name] = value;
3695
+ if (!this.options)
3696
+ this.options = {};
3697
+ if (/^features\./.test(name)) {
3698
+ util.setProperty(this.options, name, value, ifNotSet);
3699
+ } else if (!ifNotSet || this.options[name] === undefined) {
3700
+ if (this.getOption(name) !== value) this.resolved = false;
3701
+ this.options[name] = value;
3702
+ }
3703
+
3410
3704
  return this;
3411
3705
  };
3412
3706
 
@@ -3430,10 +3724,11 @@ ReflectionObject.prototype.setParsedOption = function setParsedOption(name, valu
3430
3724
  });
3431
3725
  if (opt) {
3432
3726
  // If we found an existing option - just merge the property value
3727
+ // (If it's a feature, will just write over)
3433
3728
  var newValue = opt[name];
3434
3729
  util.setProperty(newValue, propName, value);
3435
3730
  } else {
3436
- // otherwise, create a new option, set it's property and add it to the list
3731
+ // otherwise, create a new option, set its property and add it to the list
3437
3732
  opt = {};
3438
3733
  opt[name] = util.setProperty({}, propName, value);
3439
3734
  parsedOptions.push(opt);
@@ -3444,6 +3739,7 @@ ReflectionObject.prototype.setParsedOption = function setParsedOption(name, valu
3444
3739
  newOpt[name] = value;
3445
3740
  parsedOptions.push(newOpt);
3446
3741
  }
3742
+
3447
3743
  return this;
3448
3744
  };
3449
3745
 
@@ -3472,12 +3768,25 @@ ReflectionObject.prototype.toString = function toString() {
3472
3768
  return className;
3473
3769
  };
3474
3770
 
3771
+ /**
3772
+ * Converts the edition this object is pinned to for JSON format.
3773
+ * @returns {string|undefined} The edition string for JSON representation
3774
+ */
3775
+ ReflectionObject.prototype._editionToJSON = function _editionToJSON() {
3776
+ if (!this._edition || this._edition === "proto3") {
3777
+ // Avoid emitting proto3 since we need to default to it for backwards
3778
+ // compatibility anyway.
3779
+ return undefined;
3780
+ }
3781
+ return this._edition;
3782
+ };
3783
+
3475
3784
  // Sets up cyclic dependencies (called in index-light)
3476
3785
  ReflectionObject._configure = function(Root_) {
3477
3786
  Root = Root_;
3478
3787
  };
3479
3788
 
3480
- },{"33":33}],23:[function(require,module,exports){
3789
+ },{"23":23,"33":33}],23:[function(require,module,exports){
3481
3790
  "use strict";
3482
3791
  module.exports = OneOf;
3483
3792
 
@@ -3651,6 +3960,25 @@ OneOf.prototype.onRemove = function onRemove(parent) {
3651
3960
  ReflectionObject.prototype.onRemove.call(this, parent);
3652
3961
  };
3653
3962
 
3963
+ /**
3964
+ * Determines whether this field corresponds to a synthetic oneof created for
3965
+ * a proto3 optional field. No behavioral logic should depend on this, but it
3966
+ * can be relevant for reflection.
3967
+ * @name OneOf#isProto3Optional
3968
+ * @type {boolean}
3969
+ * @readonly
3970
+ */
3971
+ Object.defineProperty(OneOf.prototype, "isProto3Optional", {
3972
+ get: function() {
3973
+ if (this.fieldsArray == null || this.fieldsArray.length !== 1) {
3974
+ return false;
3975
+ }
3976
+
3977
+ var field = this.fieldsArray[0];
3978
+ return field.options != null && field.options["proto3_optional"] === true;
3979
+ }
3980
+ });
3981
+
3654
3982
  /**
3655
3983
  * Decorator function as returned by {@link OneOf.d} (TypeScript).
3656
3984
  * @typedef OneOfDecorator
@@ -4191,11 +4519,14 @@ function Root(options) {
4191
4519
  * @type {string[]}
4192
4520
  */
4193
4521
  this.files = [];
4522
+
4523
+ // Default to proto2 if unspecified.
4524
+ this._edition = "proto2";
4194
4525
  }
4195
4526
 
4196
4527
  /**
4197
4528
  * Loads a namespace descriptor into a root namespace.
4198
- * @param {INamespace} json Nameespace descriptor
4529
+ * @param {INamespace} json Namespace descriptor
4199
4530
  * @param {Root} [root] Root namespace, defaults to create a new one if omitted
4200
4531
  * @returns {Root} Root namespace
4201
4532
  */
@@ -4204,7 +4535,7 @@ Root.fromJSON = function fromJSON(json, root) {
4204
4535
  root = new Root();
4205
4536
  if (json.options)
4206
4537
  root.setOptions(json.options);
4207
- return root.addJSON(json.nested);
4538
+ return root.addJSON(json.nested)._resolveFeaturesRecursive();
4208
4539
  };
4209
4540
 
4210
4541
  /**
@@ -4244,18 +4575,24 @@ Root.prototype.load = function load(filename, options, callback) {
4244
4575
  options = undefined;
4245
4576
  }
4246
4577
  var self = this;
4247
- if (!callback)
4578
+ if (!callback) {
4248
4579
  return util.asPromise(load, self, filename, options);
4580
+ }
4249
4581
 
4250
4582
  var sync = callback === SYNC; // undocumented
4251
4583
 
4252
4584
  // Finishes loading by calling the callback (exactly once)
4253
4585
  function finish(err, root) {
4586
+ if (root) {
4587
+ root._resolveFeaturesRecursive();
4588
+ }
4254
4589
  /* istanbul ignore if */
4255
- if (!callback)
4590
+ if (!callback) {
4256
4591
  return;
4257
- if (sync)
4592
+ }
4593
+ if (sync) {
4258
4594
  throw err;
4595
+ }
4259
4596
  var cb = callback;
4260
4597
  callback = null;
4261
4598
  cb(err, root);
@@ -4295,8 +4632,9 @@ Root.prototype.load = function load(filename, options, callback) {
4295
4632
  } catch (err) {
4296
4633
  finish(err);
4297
4634
  }
4298
- if (!sync && !queued)
4635
+ if (!sync && !queued) {
4299
4636
  finish(null, self); // only once anyway
4637
+ }
4300
4638
  }
4301
4639
 
4302
4640
  // Fetches a single file
@@ -4304,15 +4642,16 @@ Root.prototype.load = function load(filename, options, callback) {
4304
4642
  filename = getBundledFileName(filename) || filename;
4305
4643
 
4306
4644
  // Skip if already loaded / attempted
4307
- if (self.files.indexOf(filename) > -1)
4645
+ if (self.files.indexOf(filename) > -1) {
4308
4646
  return;
4647
+ }
4309
4648
  self.files.push(filename);
4310
4649
 
4311
4650
  // Shortcut bundled definitions
4312
4651
  if (filename in common) {
4313
- if (sync)
4652
+ if (sync) {
4314
4653
  process(filename, common[filename]);
4315
- else {
4654
+ } else {
4316
4655
  ++queued;
4317
4656
  setTimeout(function() {
4318
4657
  --queued;
@@ -4338,8 +4677,9 @@ Root.prototype.load = function load(filename, options, callback) {
4338
4677
  self.fetch(filename, function(err, source) {
4339
4678
  --queued;
4340
4679
  /* istanbul ignore if */
4341
- if (!callback)
4680
+ if (!callback) {
4342
4681
  return; // terminated meanwhile
4682
+ }
4343
4683
  if (err) {
4344
4684
  /* istanbul ignore else */
4345
4685
  if (!weak)
@@ -4356,17 +4696,21 @@ Root.prototype.load = function load(filename, options, callback) {
4356
4696
 
4357
4697
  // Assembling the root namespace doesn't require working type
4358
4698
  // references anymore, so we can load everything in parallel
4359
- if (util.isString(filename))
4699
+ if (util.isString(filename)) {
4360
4700
  filename = [ filename ];
4701
+ }
4361
4702
  for (var i = 0, resolved; i < filename.length; ++i)
4362
4703
  if (resolved = self.resolvePath("", filename[i]))
4363
4704
  fetch(resolved);
4364
-
4365
- if (sync)
4705
+ if (sync) {
4706
+ self._resolveFeaturesRecursive();
4366
4707
  return self;
4367
- if (!queued)
4708
+ }
4709
+ if (!queued) {
4368
4710
  finish(null, self);
4369
- return undefined;
4711
+ }
4712
+
4713
+ return self;
4370
4714
  };
4371
4715
  // function load(filename:string, options:IParseOptions, callback:LoadCallback):undefined
4372
4716
 
@@ -4412,6 +4756,7 @@ Root.prototype.resolveAll = function resolveAll() {
4412
4756
  throw Error("unresolvable extensions: " + this.deferred.map(function(field) {
4413
4757
  return "'extend " + field.extend + "' in " + field.parent.fullName;
4414
4758
  }).join(", "));
4759
+ this._resolveFeaturesRecursive(this._edition);
4415
4760
  return Namespace.prototype.resolveAll.call(this);
4416
4761
  };
4417
4762
 
@@ -4785,7 +5130,10 @@ Service.fromJSON = function fromJSON(name, json) {
4785
5130
  service.add(Method.fromJSON(names[i], json.methods[names[i]]));
4786
5131
  if (json.nested)
4787
5132
  service.addJSON(json.nested);
5133
+ if (json.edition)
5134
+ service._edition = json.edition;
4788
5135
  service.comment = json.comment;
5136
+ service._defaultEdition = "proto3"; // For backwards-compatibility.
4789
5137
  return service;
4790
5138
  };
4791
5139
 
@@ -4798,6 +5146,7 @@ Service.prototype.toJSON = function toJSON(toJSONOptions) {
4798
5146
  var inherited = Namespace.prototype.toJSON.call(this, toJSONOptions);
4799
5147
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
4800
5148
  return util.toObject([
5149
+ "edition" , this._editionToJSON(),
4801
5150
  "options" , inherited && inherited.options || undefined,
4802
5151
  "methods" , Namespace.arrayToJSON(this.methodsArray, toJSONOptions) || /* istanbul ignore next */ {},
4803
5152
  "nested" , inherited && inherited.nested || undefined,
@@ -4834,10 +5183,26 @@ Service.prototype.get = function get(name) {
4834
5183
  * @override
4835
5184
  */
4836
5185
  Service.prototype.resolveAll = function resolveAll() {
5186
+ Namespace.prototype.resolve.call(this);
4837
5187
  var methods = this.methodsArray;
4838
5188
  for (var i = 0; i < methods.length; ++i)
4839
5189
  methods[i].resolve();
4840
- return Namespace.prototype.resolve.call(this);
5190
+ return this;
5191
+ };
5192
+
5193
+ /**
5194
+ * @override
5195
+ */
5196
+ Service.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
5197
+ if (!this._needsRecursiveFeatureResolution) return this;
5198
+
5199
+ edition = this._edition || edition;
5200
+
5201
+ Namespace.prototype._resolveFeaturesRecursive.call(this, edition);
5202
+ this.methodsArray.forEach(method => {
5203
+ method._resolveFeaturesRecursive(edition);
5204
+ });
5205
+ return this;
4841
5206
  };
4842
5207
 
4843
5208
  /**
@@ -5169,6 +5534,9 @@ Type.fromJSON = function fromJSON(name, json) {
5169
5534
  type.group = true;
5170
5535
  if (json.comment)
5171
5536
  type.comment = json.comment;
5537
+ if (json.edition)
5538
+ type._edition = json.edition;
5539
+ type._defaultEdition = "proto3"; // For backwards-compatibility.
5172
5540
  return type;
5173
5541
  };
5174
5542
 
@@ -5181,6 +5549,7 @@ Type.prototype.toJSON = function toJSON(toJSONOptions) {
5181
5549
  var inherited = Namespace.prototype.toJSON.call(this, toJSONOptions);
5182
5550
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
5183
5551
  return util.toObject([
5552
+ "edition" , this._editionToJSON(),
5184
5553
  "options" , inherited && inherited.options || undefined,
5185
5554
  "oneofs" , Namespace.arrayToJSON(this.oneofsArray, toJSONOptions),
5186
5555
  "fields" , Namespace.arrayToJSON(this.fieldsArray.filter(function(obj) { return !obj.declaringField; }), toJSONOptions) || {},
@@ -5196,13 +5565,32 @@ Type.prototype.toJSON = function toJSON(toJSONOptions) {
5196
5565
  * @override
5197
5566
  */
5198
5567
  Type.prototype.resolveAll = function resolveAll() {
5199
- var fields = this.fieldsArray, i = 0;
5200
- while (i < fields.length)
5201
- fields[i++].resolve();
5568
+ Namespace.prototype.resolveAll.call(this);
5202
5569
  var oneofs = this.oneofsArray; i = 0;
5203
5570
  while (i < oneofs.length)
5204
5571
  oneofs[i++].resolve();
5205
- return Namespace.prototype.resolveAll.call(this);
5572
+ var fields = this.fieldsArray, i = 0;
5573
+ while (i < fields.length)
5574
+ fields[i++].resolve();
5575
+ return this;
5576
+ };
5577
+
5578
+ /**
5579
+ * @override
5580
+ */
5581
+ Type.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
5582
+ if (!this._needsRecursiveFeatureResolution) return this;
5583
+
5584
+ edition = this._edition || edition;
5585
+
5586
+ Namespace.prototype._resolveFeaturesRecursive.call(this, edition);
5587
+ this.oneofsArray.forEach(oneof => {
5588
+ oneof._resolveFeatures(edition);
5589
+ });
5590
+ this.fieldsArray.forEach(field => {
5591
+ field._resolveFeatures(edition);
5592
+ });
5593
+ return this;
5206
5594
  };
5207
5595
 
5208
5596
  /**
@@ -5857,9 +6245,10 @@ util.decorateEnum = function decorateEnum(object) {
5857
6245
  * @param {Object.<string,*>} dst Destination object
5858
6246
  * @param {string} path dot '.' delimited path of the property to set
5859
6247
  * @param {Object} value the value to set
6248
+ * @param {boolean|undefined} [ifNotSet] Sets the option only if it isn't currently set
5860
6249
  * @returns {Object.<string,*>} Destination object
5861
6250
  */
5862
- util.setProperty = function setProperty(dst, path, value) {
6251
+ util.setProperty = function setProperty(dst, path, value, ifNotSet) {
5863
6252
  function setProp(dst, path, value) {
5864
6253
  var part = path.shift();
5865
6254
  if (part === "__proto__" || part === "prototype") {
@@ -5869,6 +6258,8 @@ util.setProperty = function setProperty(dst, path, value) {
5869
6258
  dst[part] = setProp(dst[part] || {}, path, value);
5870
6259
  } else {
5871
6260
  var prevValue = dst[part];
6261
+ if (prevValue && ifNotSet)
6262
+ return dst;
5872
6263
  if (prevValue)
5873
6264
  value = [].concat(prevValue).concat(value);
5874
6265
  dst[part] = value;