protobufjs 8.0.3-experimental → 8.1.0-experimental

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 v8.0.3-experimental (c) 2016, daniel wirtz
3
- * compiled tue, 25 mar 2025 02:15:04 utc
2
+ * protobuf.js v8.1.0-experimental (c) 2016, daniel wirtz
3
+ * compiled wed, 07 may 2025 17:43:49 utc
4
4
  * licensed under the bsd-3-clause license
5
5
  * see: https://github.com/dcodeio/protobuf.js for details
6
6
  */
@@ -1707,12 +1707,6 @@ function Enum(name, values, options, comment, comments, valuesOptions) {
1707
1707
  */
1708
1708
  this._valuesFeatures = {};
1709
1709
 
1710
- /**
1711
- * Unresolved values features, if any
1712
- * @type {Object<string, Object<string, *>>|undefined}
1713
- */
1714
- this._valuesProtoFeatures = {};
1715
-
1716
1710
  /**
1717
1711
  * Reserved ranges, if any.
1718
1712
  * @type {Array.<number[]|string>}
@@ -1730,21 +1724,20 @@ function Enum(name, values, options, comment, comments, valuesOptions) {
1730
1724
  }
1731
1725
 
1732
1726
  /**
1733
- * Resolves value features
1734
- * @returns {Enum} `this`
1727
+ * @override
1735
1728
  */
1736
- Enum.prototype.resolve = function resolve() {
1737
- ReflectionObject.prototype.resolve.call(this);
1729
+ Enum.prototype._resolveFeatures = function _resolveFeatures(edition) {
1730
+ edition = this._edition || edition;
1731
+ ReflectionObject.prototype._resolveFeatures.call(this, edition);
1738
1732
 
1739
- for (var key of Object.keys(this._valuesProtoFeatures)) {
1733
+ Object.keys(this.values).forEach(key => {
1740
1734
  var parentFeaturesCopy = Object.assign({}, this._features);
1741
- this._valuesFeatures[key] = Object.assign(parentFeaturesCopy, this._valuesProtoFeatures[key] || {});
1742
- }
1735
+ this._valuesFeatures[key] = Object.assign(parentFeaturesCopy, this.valuesOptions && this.valuesOptions[key] && this.valuesOptions[key].features);
1736
+ });
1743
1737
 
1744
1738
  return this;
1745
1739
  };
1746
1740
 
1747
-
1748
1741
  /**
1749
1742
  * Enum descriptor.
1750
1743
  * @interface IEnum
@@ -1762,6 +1755,9 @@ Enum.prototype.resolve = function resolve() {
1762
1755
  Enum.fromJSON = function fromJSON(name, json) {
1763
1756
  var enm = new Enum(name, json.values, json.options, json.comment, json.comments);
1764
1757
  enm.reserved = json.reserved;
1758
+ if (json.edition)
1759
+ enm._edition = json.edition;
1760
+ enm._defaultEdition = "proto3"; // For backwards-compatibility.
1765
1761
  return enm;
1766
1762
  };
1767
1763
 
@@ -1773,6 +1769,7 @@ Enum.fromJSON = function fromJSON(name, json) {
1773
1769
  Enum.prototype.toJSON = function toJSON(toJSONOptions) {
1774
1770
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
1775
1771
  return util.toObject([
1772
+ "edition" , this._editionToJSON(),
1776
1773
  "options" , this.options,
1777
1774
  "valuesOptions" , this.valuesOptions,
1778
1775
  "values" , this.values,
@@ -1821,21 +1818,6 @@ Enum.prototype.add = function add(name, id, comment, options) {
1821
1818
  if (this.valuesOptions === undefined)
1822
1819
  this.valuesOptions = {};
1823
1820
  this.valuesOptions[name] = options || null;
1824
-
1825
- for (var key of Object.keys(this.valuesOptions)) {
1826
- var features = Array.isArray(this.valuesOptions[key]) ? this.valuesOptions[key].find(x => {return Object.prototype.hasOwnProperty.call(x, "features");}) : this.valuesOptions[key] === "features";
1827
- if (features) {
1828
- this._valuesProtoFeatures[key] = features.features;
1829
- } else {
1830
- this._valuesProtoFeatures[key] = {};
1831
- }
1832
- }
1833
- }
1834
-
1835
- for (var enumValue of Object.keys(this.values)) {
1836
- if (!this._valuesProtoFeatures[enumValue]) {
1837
- this._valuesProtoFeatures[enumValue] = {};
1838
- }
1839
1821
  }
1840
1822
 
1841
1823
  this.comments[name] = comment || null;
@@ -1923,7 +1905,11 @@ var ruleRe = /^required|optional|repeated$/;
1923
1905
  * @throws {TypeError} If arguments are invalid
1924
1906
  */
1925
1907
  Field.fromJSON = function fromJSON(name, json) {
1926
- 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;
1927
1913
  };
1928
1914
 
1929
1915
  /**
@@ -2164,6 +2150,7 @@ Field.prototype.setOption = function setOption(name, value, ifNotSet) {
2164
2150
  Field.prototype.toJSON = function toJSON(toJSONOptions) {
2165
2151
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
2166
2152
  return util.toObject([
2153
+ "edition" , this._editionToJSON(),
2167
2154
  "rule" , this.rule !== "optional" && this.rule || undefined,
2168
2155
  "type" , this.type,
2169
2156
  "id" , this.id,
@@ -2248,14 +2235,23 @@ Field.prototype.resolve = function resolve() {
2248
2235
  * @returns {object} The feature values to override
2249
2236
  */
2250
2237
  Field.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(edition) {
2251
- if (edition) return {};
2238
+ if (edition !== "proto2" && edition !== "proto3") {
2239
+ return {};
2240
+ }
2252
2241
 
2253
2242
  var features = {};
2243
+
2254
2244
  if (this.rule === "required") {
2255
2245
  features.field_presence = "LEGACY_REQUIRED";
2256
2246
  }
2257
- if (this.resolvedType instanceof Type && this.resolvedType.group) {
2258
- features.message_encoding = "DELIMITED";
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
+ }
2259
2255
  }
2260
2256
  if (this.getOption("packed") === true) {
2261
2257
  features.repeated_field_encoding = "PACKED";
@@ -2265,6 +2261,13 @@ Field.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(e
2265
2261
  return features;
2266
2262
  };
2267
2263
 
2264
+ /**
2265
+ * @override
2266
+ */
2267
+ Field.prototype._resolveFeatures = function _resolveFeatures(edition) {
2268
+ return ReflectionObject.prototype._resolveFeatures.call(this, this._edition || edition);
2269
+ };
2270
+
2268
2271
  /**
2269
2272
  * Decorator function as returned by {@link Field.d} and {@link MapField.d} (TypeScript).
2270
2273
  * @typedef FieldDecorator
@@ -2420,7 +2423,7 @@ protobuf.types = require(32);
2420
2423
  protobuf.util = require(33);
2421
2424
 
2422
2425
  // Set up possibly cyclic reflection dependencies
2423
- protobuf.ReflectionObject._configure(protobuf.Root, protobuf.Namespace);
2426
+ protobuf.ReflectionObject._configure(protobuf.Root);
2424
2427
  protobuf.Namespace._configure(protobuf.Type, protobuf.Service, protobuf.Enum);
2425
2428
  protobuf.Root._configure(protobuf.Type);
2426
2429
  protobuf.Field._configure(protobuf.Type);
@@ -3136,6 +3139,15 @@ Namespace.prototype.add = function add(object) {
3136
3139
  }
3137
3140
  }
3138
3141
  this.nested[object.name] = object;
3142
+
3143
+ if (!(this instanceof Type || this instanceof Service || this instanceof Enum || this instanceof Field)) {
3144
+ // This is a package or a root namespace.
3145
+ if (!object._edition) {
3146
+ // Make sure that some edition is set if it hasn't already been specified.
3147
+ object._edition = object._defaultEdition;
3148
+ }
3149
+ }
3150
+
3139
3151
  object.onAdd(this);
3140
3152
  return clearCache(this);
3141
3153
  };
@@ -3207,6 +3219,19 @@ Namespace.prototype.resolveAll = function resolveAll() {
3207
3219
  return this;
3208
3220
  };
3209
3221
 
3222
+ /**
3223
+ * @override
3224
+ */
3225
+ Namespace.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
3226
+ edition = this._edition || edition;
3227
+
3228
+ ReflectionObject.prototype._resolveFeaturesRecursive.call(this, edition);
3229
+ this.nestedArray.forEach(nested => {
3230
+ nested._resolveFeaturesRecursive(edition);
3231
+ });
3232
+ return this;
3233
+ };
3234
+
3210
3235
  /**
3211
3236
  * Recursively looks up the reflection object matching the specified path in the scope of this namespace.
3212
3237
  * @param {string|string[]} path Path to look up
@@ -3338,7 +3363,7 @@ ReflectionObject.className = "ReflectionObject";
3338
3363
  const OneOf = require(23);
3339
3364
  var util = require(33);
3340
3365
 
3341
- var Root, Namespace; // cyclic
3366
+ var Root; // cyclic
3342
3367
 
3343
3368
  /* eslint-disable no-warning-comments */
3344
3369
  // TODO: Replace with embedded proto.
@@ -3381,14 +3406,23 @@ function ReflectionObject(name, options) {
3381
3406
  this.name = name;
3382
3407
 
3383
3408
  /**
3384
- * Resolved Features.
3409
+ * The edition specified for this object. Only relevant for top-level objects.
3410
+ * @type {string}
3385
3411
  */
3386
- this._features = {};
3412
+ this._edition = null;
3387
3413
 
3388
3414
  /**
3389
- * Unresolved Features.
3415
+ * The default edition to use for this object if none is specified. For legacy reasons,
3416
+ * this is proto2 except in the JSON parsing case where it was proto3.
3417
+ * @type {string}
3390
3418
  */
3391
- this._protoFeatures = null;
3419
+ this._defaultEdition = "proto2";
3420
+
3421
+ /**
3422
+ * Resolved Features.
3423
+ * @type {object}
3424
+ */
3425
+ this._features = {};
3392
3426
 
3393
3427
  /**
3394
3428
  * Parent namespace.
@@ -3495,26 +3529,41 @@ ReflectionObject.prototype.onRemove = function onRemove(parent) {
3495
3529
  ReflectionObject.prototype.resolve = function resolve() {
3496
3530
  if (this.resolved)
3497
3531
  return this;
3498
- var edition = this.getOption("edition");
3499
- if ((this instanceof Namespace && edition) || (this.parent && this.parent.resolved)) {
3500
- this._resolveFeatures();
3532
+ if (this instanceof Root) {
3533
+ this._resolveFeaturesRecursive(this._edition);
3501
3534
  this.resolved = true;
3502
3535
  }
3503
3536
  return this;
3504
3537
  };
3505
3538
 
3539
+ /**
3540
+ * Resolves this objects editions features.
3541
+ * @param {string} edition The edition we're currently resolving for.
3542
+ * @returns {ReflectionObject} `this`
3543
+ */
3544
+ ReflectionObject.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
3545
+ return this._resolveFeatures(this._edition || edition);
3546
+ };
3547
+
3506
3548
  /**
3507
3549
  * Resolves child features from parent features
3550
+ * @param {string} edition The edition we're currently resolving for.
3508
3551
  * @returns {undefined}
3509
3552
  */
3510
- ReflectionObject.prototype._resolveFeatures = function _resolveFeatures() {
3553
+ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition) {
3511
3554
  var defaults = {};
3512
3555
 
3513
- var protoFeatures = Object.assign(Object.assign({}, this._protoFeatures), this._inferLegacyProtoFeatures(edition));
3556
+ /* istanbul ignore if */
3557
+ if (!edition) {
3558
+ throw new Error("Unknown edition for " + this.fullName);
3559
+ }
3560
+
3561
+ var protoFeatures = Object.assign(this.options ? Object.assign({}, this.options.features) : {},
3562
+ this._inferLegacyProtoFeatures(edition));
3514
3563
 
3515
- var edition = this.getOption("edition");
3516
- if (this instanceof Namespace && edition) {
3564
+ if (this._edition) {
3517
3565
  // For a namespace marked with a specific edition, reset defaults.
3566
+ /* istanbul ignore else */
3518
3567
  if (edition === "proto2") {
3519
3568
  defaults = Object.assign({}, proto2Defaults);
3520
3569
  } else if (edition === "proto3") {
@@ -3530,6 +3579,7 @@ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures() {
3530
3579
 
3531
3580
  // fields in Oneofs aren't actually children of them, so we have to
3532
3581
  // special-case it
3582
+ /* istanbul ignore else */
3533
3583
  if (this.partOf instanceof OneOf) {
3534
3584
  var lexicalParentFeaturesCopy = Object.assign({}, this.partOf._features);
3535
3585
  this._features = Object.assign(lexicalParentFeaturesCopy, protoFeatures || {});
@@ -3539,7 +3589,7 @@ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures() {
3539
3589
  var parentFeaturesCopy = Object.assign({}, this.parent._features);
3540
3590
  this._features = Object.assign(parentFeaturesCopy, protoFeatures || {});
3541
3591
  } else {
3542
- this._features = Object.assign({}, protoFeatures);
3592
+ throw new Error("Unable to find a parent for " + this.fullName);
3543
3593
  }
3544
3594
  if (this.extensionField) {
3545
3595
  // Sister fields should have the same features as their extensions.
@@ -3552,7 +3602,6 @@ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures() {
3552
3602
  * in older editions.
3553
3603
  * @param {string|undefined} edition The edition this proto is on, or undefined if pre-editions
3554
3604
  * @returns {object} The feature values to override
3555
- * @abstract
3556
3605
  */
3557
3606
  ReflectionObject.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(/*edition*/) {
3558
3607
  return {};
@@ -3573,14 +3622,19 @@ ReflectionObject.prototype.getOption = function getOption(name) {
3573
3622
  * Sets an option.
3574
3623
  * @param {string} name Option name
3575
3624
  * @param {*} value Option value
3576
- * @param {boolean} [ifNotSet] Sets the option only if it isn't currently set
3625
+ * @param {boolean|undefined} [ifNotSet] Sets the option only if it isn't currently set
3577
3626
  * @returns {ReflectionObject} `this`
3578
3627
  */
3579
3628
  ReflectionObject.prototype.setOption = function setOption(name, value, ifNotSet) {
3580
- if (!ifNotSet || !this.options || this.options[name] === undefined) {
3629
+ if (!this.options)
3630
+ this.options = {};
3631
+ if (/^features\./.test(name)) {
3632
+ util.setProperty(this.options, name, value, ifNotSet);
3633
+ } else if (!ifNotSet || this.options[name] === undefined) {
3581
3634
  if (this.getOption(name) !== value) this.resolved = false;
3582
- (this.options || (this.options = {}))[name] = value;
3635
+ this.options[name] = value;
3583
3636
  }
3637
+
3584
3638
  return this;
3585
3639
  };
3586
3640
 
@@ -3595,7 +3649,6 @@ ReflectionObject.prototype.setParsedOption = function setParsedOption(name, valu
3595
3649
  if (!this.parsedOptions) {
3596
3650
  this.parsedOptions = [];
3597
3651
  }
3598
- var isFeature = /^features$/.test(name);
3599
3652
  var parsedOptions = this.parsedOptions;
3600
3653
  if (propName) {
3601
3654
  // If setting a sub property of an option then try to merge it
@@ -3621,12 +3674,6 @@ ReflectionObject.prototype.setParsedOption = function setParsedOption(name, valu
3621
3674
  parsedOptions.push(newOpt);
3622
3675
  }
3623
3676
 
3624
-
3625
- if (isFeature) {
3626
- var features = parsedOptions.find(x => {return Object.prototype.hasOwnProperty.call(x, "features");});
3627
- this._protoFeatures = features.features || {};
3628
- }
3629
-
3630
3677
  return this;
3631
3678
  };
3632
3679
 
@@ -3655,10 +3702,22 @@ ReflectionObject.prototype.toString = function toString() {
3655
3702
  return className;
3656
3703
  };
3657
3704
 
3705
+ /**
3706
+ * Converts the edition this object is pinned to for JSON format.
3707
+ * @returns {string|undefined} The edition string for JSON representation
3708
+ */
3709
+ ReflectionObject.prototype._editionToJSON = function _editionToJSON() {
3710
+ if (!this._edition || this._edition === "proto3") {
3711
+ // Avoid emitting proto3 since we need to default to it for backwards
3712
+ // compatibility anyway.
3713
+ return undefined;
3714
+ }
3715
+ return this._edition;
3716
+ };
3717
+
3658
3718
  // Sets up cyclic dependencies (called in index-light)
3659
- ReflectionObject._configure = function(Root_, Namespace_) {
3719
+ ReflectionObject._configure = function(Root_) {
3660
3720
  Root = Root_;
3661
- Namespace = Namespace_;
3662
3721
  };
3663
3722
 
3664
3723
  },{"23":23,"33":33}],23:[function(require,module,exports){
@@ -4395,8 +4454,8 @@ function Root(options) {
4395
4454
  */
4396
4455
  this.files = [];
4397
4456
 
4398
- // Default to proto2 if not specified.
4399
- this.setOption("edition", "proto2", true);
4457
+ // Default to proto2 if unspecified.
4458
+ this._edition = "proto2";
4400
4459
  }
4401
4460
 
4402
4461
  /**
@@ -4410,7 +4469,7 @@ Root.fromJSON = function fromJSON(json, root) {
4410
4469
  root = new Root();
4411
4470
  if (json.options)
4412
4471
  root.setOptions(json.options);
4413
- return root.addJSON(json.nested);
4472
+ return root.addJSON(json.nested)._resolveFeaturesRecursive();
4414
4473
  };
4415
4474
 
4416
4475
  /**
@@ -4458,6 +4517,9 @@ Root.prototype.load = function load(filename, options, callback) {
4458
4517
 
4459
4518
  // Finishes loading by calling the callback (exactly once)
4460
4519
  function finish(err, root) {
4520
+ if (root) {
4521
+ root._resolveFeaturesRecursive();
4522
+ }
4461
4523
  /* istanbul ignore if */
4462
4524
  if (!callback) {
4463
4525
  return;
@@ -4467,9 +4529,6 @@ Root.prototype.load = function load(filename, options, callback) {
4467
4529
  }
4468
4530
  var cb = callback;
4469
4531
  callback = null;
4470
- if (root) {
4471
- root.resolveAll();
4472
- }
4473
4532
  cb(err, root);
4474
4533
  }
4475
4534
 
@@ -4577,8 +4636,8 @@ Root.prototype.load = function load(filename, options, callback) {
4577
4636
  for (var i = 0, resolved; i < filename.length; ++i)
4578
4637
  if (resolved = self.resolvePath("", filename[i]))
4579
4638
  fetch(resolved);
4580
- self.resolveAll();
4581
4639
  if (sync) {
4640
+ self._resolveFeaturesRecursive();
4582
4641
  return self;
4583
4642
  }
4584
4643
  if (!queued) {
@@ -5004,7 +5063,10 @@ Service.fromJSON = function fromJSON(name, json) {
5004
5063
  service.add(Method.fromJSON(names[i], json.methods[names[i]]));
5005
5064
  if (json.nested)
5006
5065
  service.addJSON(json.nested);
5066
+ if (json.edition)
5067
+ service._edition = json.edition;
5007
5068
  service.comment = json.comment;
5069
+ service._defaultEdition = "proto3"; // For backwards-compatibility.
5008
5070
  return service;
5009
5071
  };
5010
5072
 
@@ -5017,6 +5079,7 @@ Service.prototype.toJSON = function toJSON(toJSONOptions) {
5017
5079
  var inherited = Namespace.prototype.toJSON.call(this, toJSONOptions);
5018
5080
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
5019
5081
  return util.toObject([
5082
+ "edition" , this._editionToJSON(),
5020
5083
  "options" , inherited && inherited.options || undefined,
5021
5084
  "methods" , Namespace.arrayToJSON(this.methodsArray, toJSONOptions) || /* istanbul ignore next */ {},
5022
5085
  "nested" , inherited && inherited.nested || undefined,
@@ -5060,6 +5123,19 @@ Service.prototype.resolveAll = function resolveAll() {
5060
5123
  return this;
5061
5124
  };
5062
5125
 
5126
+ /**
5127
+ * @override
5128
+ */
5129
+ Service.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
5130
+ edition = this._edition || edition;
5131
+
5132
+ Namespace.prototype._resolveFeaturesRecursive.call(this, edition);
5133
+ this.methodsArray.forEach(method => {
5134
+ method._resolveFeaturesRecursive(edition);
5135
+ });
5136
+ return this;
5137
+ };
5138
+
5063
5139
  /**
5064
5140
  * @override
5065
5141
  */
@@ -5389,6 +5465,9 @@ Type.fromJSON = function fromJSON(name, json) {
5389
5465
  type.group = true;
5390
5466
  if (json.comment)
5391
5467
  type.comment = json.comment;
5468
+ if (json.edition)
5469
+ type._edition = json.edition;
5470
+ type._defaultEdition = "proto3"; // For backwards-compatibility.
5392
5471
  return type;
5393
5472
  };
5394
5473
 
@@ -5401,6 +5480,7 @@ Type.prototype.toJSON = function toJSON(toJSONOptions) {
5401
5480
  var inherited = Namespace.prototype.toJSON.call(this, toJSONOptions);
5402
5481
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
5403
5482
  return util.toObject([
5483
+ "edition" , this._editionToJSON(),
5404
5484
  "options" , inherited && inherited.options || undefined,
5405
5485
  "oneofs" , Namespace.arrayToJSON(this.oneofsArray, toJSONOptions),
5406
5486
  "fields" , Namespace.arrayToJSON(this.fieldsArray.filter(function(obj) { return !obj.declaringField; }), toJSONOptions) || {},
@@ -5426,6 +5506,22 @@ Type.prototype.resolveAll = function resolveAll() {
5426
5506
  return this;
5427
5507
  };
5428
5508
 
5509
+ /**
5510
+ * @override
5511
+ */
5512
+ Type.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
5513
+ edition = this._edition || edition;
5514
+
5515
+ Namespace.prototype._resolveFeaturesRecursive.call(this, edition);
5516
+ this.oneofsArray.forEach(oneof => {
5517
+ oneof._resolveFeatures(edition);
5518
+ });
5519
+ this.fieldsArray.forEach(field => {
5520
+ field._resolveFeatures(edition);
5521
+ });
5522
+ return this;
5523
+ };
5524
+
5429
5525
  /**
5430
5526
  * @override
5431
5527
  */
@@ -6078,10 +6174,10 @@ util.decorateEnum = function decorateEnum(object) {
6078
6174
  * @param {Object.<string,*>} dst Destination object
6079
6175
  * @param {string} path dot '.' delimited path of the property to set
6080
6176
  * @param {Object} value the value to set
6081
- * @param {boolean} overWrite whether or not to concatenate the values into an array or overwrite; defaults to false.
6177
+ * @param {boolean|undefined} [ifNotSet] Sets the option only if it isn't currently set
6082
6178
  * @returns {Object.<string,*>} Destination object
6083
6179
  */
6084
- util.setProperty = function setProperty(dst, path, value) {
6180
+ util.setProperty = function setProperty(dst, path, value, ifNotSet) {
6085
6181
  function setProp(dst, path, value) {
6086
6182
  var part = path.shift();
6087
6183
  if (part === "__proto__" || part === "prototype") {
@@ -6091,6 +6187,8 @@ util.setProperty = function setProperty(dst, path, value) {
6091
6187
  dst[part] = setProp(dst[part] || {}, path, value);
6092
6188
  } else {
6093
6189
  var prevValue = dst[part];
6190
+ if (prevValue && ifNotSet)
6191
+ return dst;
6094
6192
  if (prevValue)
6095
6193
  value = [].concat(prevValue).concat(value);
6096
6194
  dst[part] = value;