protobufjs 8.0.3-experimental → 8.0.4-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.0.4-experimental (c) 2016, daniel wirtz
3
+ * compiled thu, 27 mar 2025 04:14:10 utc
4
4
  * licensed under the bsd-3-clause license
5
5
  * see: https://github.com/dcodeio/protobuf.js for details
6
6
  */
@@ -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.0.4-experimental (c) 2016, daniel wirtz
3
+ * compiled thu, 27 mar 2025 04:14:10 utc
4
4
  * licensed under the bsd-3-clause license
5
5
  * see: https://github.com/dcodeio/protobuf.js for details
6
6
  */
package/dist/protobuf.js CHANGED
@@ -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.0.4-experimental (c) 2016, daniel wirtz
3
+ * compiled thu, 27 mar 2025 04:14:10 utc
4
4
  * licensed under the bsd-3-clause license
5
5
  * see: https://github.com/dcodeio/protobuf.js for details
6
6
  */
@@ -2131,21 +2131,20 @@ function Enum(name, values, options, comment, comments, valuesOptions) {
2131
2131
  }
2132
2132
 
2133
2133
  /**
2134
- * Resolves value features
2135
- * @returns {Enum} `this`
2134
+ * @override
2136
2135
  */
2137
- Enum.prototype.resolve = function resolve() {
2138
- ReflectionObject.prototype.resolve.call(this);
2136
+ Enum.prototype._resolveFeatures = function _resolveFeatures(edition) {
2137
+ var edition = this._edition || edition;
2138
+ ReflectionObject.prototype._resolveFeatures.call(this, edition);
2139
2139
 
2140
- for (var key of Object.keys(this._valuesProtoFeatures)) {
2140
+ Object.keys(this._valuesProtoFeatures).forEach(key => {
2141
2141
  var parentFeaturesCopy = Object.assign({}, this._features);
2142
2142
  this._valuesFeatures[key] = Object.assign(parentFeaturesCopy, this._valuesProtoFeatures[key] || {});
2143
- }
2143
+ });
2144
2144
 
2145
2145
  return this;
2146
2146
  };
2147
2147
 
2148
-
2149
2148
  /**
2150
2149
  * Enum descriptor.
2151
2150
  * @interface IEnum
@@ -2163,6 +2162,9 @@ Enum.prototype.resolve = function resolve() {
2163
2162
  Enum.fromJSON = function fromJSON(name, json) {
2164
2163
  var enm = new Enum(name, json.values, json.options, json.comment, json.comments);
2165
2164
  enm.reserved = json.reserved;
2165
+ if (json.edition)
2166
+ enm._edition = json.edition;
2167
+ enm._defaultEdition = "proto3"; // For backwards-compatibility.
2166
2168
  return enm;
2167
2169
  };
2168
2170
 
@@ -2174,6 +2176,7 @@ Enum.fromJSON = function fromJSON(name, json) {
2174
2176
  Enum.prototype.toJSON = function toJSON(toJSONOptions) {
2175
2177
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
2176
2178
  return util.toObject([
2179
+ "edition" , this._editionToJSON(),
2177
2180
  "options" , this.options,
2178
2181
  "valuesOptions" , this.valuesOptions,
2179
2182
  "values" , this.values,
@@ -2324,7 +2327,11 @@ var ruleRe = /^required|optional|repeated$/;
2324
2327
  * @throws {TypeError} If arguments are invalid
2325
2328
  */
2326
2329
  Field.fromJSON = function fromJSON(name, json) {
2327
- return new Field(name, json.id, json.type, json.rule, json.extend, json.options, json.comment);
2330
+ var field = new Field(name, json.id, json.type, json.rule, json.extend, json.options, json.comment);
2331
+ if (json.edition)
2332
+ field._edition = json.edition;
2333
+ field._defaultEdition = "proto3"; // For backwards-compatibility.
2334
+ return field;
2328
2335
  };
2329
2336
 
2330
2337
  /**
@@ -2565,6 +2572,7 @@ Field.prototype.setOption = function setOption(name, value, ifNotSet) {
2565
2572
  Field.prototype.toJSON = function toJSON(toJSONOptions) {
2566
2573
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
2567
2574
  return util.toObject([
2575
+ "edition" , this._editionToJSON(),
2568
2576
  "rule" , this.rule !== "optional" && this.rule || undefined,
2569
2577
  "type" , this.type,
2570
2578
  "id" , this.id,
@@ -2649,9 +2657,12 @@ Field.prototype.resolve = function resolve() {
2649
2657
  * @returns {object} The feature values to override
2650
2658
  */
2651
2659
  Field.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(edition) {
2652
- if (edition) return {};
2660
+ if (edition !== "proto2" && edition !== "proto3") {
2661
+ return;
2662
+ }
2653
2663
 
2654
2664
  var features = {};
2665
+ this.resolve();
2655
2666
  if (this.rule === "required") {
2656
2667
  features.field_presence = "LEGACY_REQUIRED";
2657
2668
  }
@@ -2666,6 +2677,13 @@ Field.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(e
2666
2677
  return features;
2667
2678
  };
2668
2679
 
2680
+ /**
2681
+ * @override
2682
+ */
2683
+ Field.prototype._resolveFeatures = function _resolveFeatures(edition) {
2684
+ return ReflectionObject.prototype._resolveFeatures.call(this, this._edition || edition);
2685
+ };
2686
+
2669
2687
  /**
2670
2688
  * Decorator function as returned by {@link Field.d} and {@link MapField.d} (TypeScript).
2671
2689
  * @typedef FieldDecorator
@@ -3551,6 +3569,15 @@ Namespace.prototype.add = function add(object) {
3551
3569
  }
3552
3570
  }
3553
3571
  this.nested[object.name] = object;
3572
+
3573
+ if (!(this instanceof Type || this instanceof Service || this instanceof Enum || this instanceof Field)) {
3574
+ // This is a package or a root namespace.
3575
+ if (!object._edition) {
3576
+ // Make sure that some edition is set if it hasn't already been specified.
3577
+ object._edition = object._defaultEdition;
3578
+ }
3579
+ }
3580
+
3554
3581
  object.onAdd(this);
3555
3582
  return clearCache(this);
3556
3583
  };
@@ -3622,6 +3649,19 @@ Namespace.prototype.resolveAll = function resolveAll() {
3622
3649
  return this;
3623
3650
  };
3624
3651
 
3652
+ /**
3653
+ * @override
3654
+ */
3655
+ Namespace.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
3656
+ var edition = this._edition || edition;
3657
+
3658
+ ReflectionObject.prototype._resolveFeaturesRecursive.call(this, edition);
3659
+ this.nestedArray.forEach(nested => {
3660
+ nested._resolveFeaturesRecursive(edition);
3661
+ });
3662
+ return this;
3663
+ };
3664
+
3625
3665
  /**
3626
3666
  * Recursively looks up the reflection object matching the specified path in the scope of this namespace.
3627
3667
  * @param {string|string[]} path Path to look up
@@ -3796,14 +3836,23 @@ function ReflectionObject(name, options) {
3796
3836
  this.name = name;
3797
3837
 
3798
3838
  /**
3799
- * Resolved Features.
3839
+ * The edition specified for this object. Only relevant for top-level objects.
3840
+ * @type {string}
3800
3841
  */
3801
- this._features = {};
3842
+ this._edition = null;
3802
3843
 
3803
3844
  /**
3804
- * Unresolved Features.
3845
+ * The default edition to use for this object if none is specified. For legacy reasons,
3846
+ * this is proto2 except in the JSON parsing case where it was proto3.
3847
+ * @type {string}
3805
3848
  */
3806
- this._protoFeatures = null;
3849
+ this._defaultEdition = "proto2";
3850
+
3851
+ /**
3852
+ * Resolved Features.
3853
+ * @type {object}
3854
+ */
3855
+ this._features = {};
3807
3856
 
3808
3857
  /**
3809
3858
  * Parent namespace.
@@ -3910,25 +3959,38 @@ ReflectionObject.prototype.onRemove = function onRemove(parent) {
3910
3959
  ReflectionObject.prototype.resolve = function resolve() {
3911
3960
  if (this.resolved)
3912
3961
  return this;
3913
- var edition = this.getOption("edition");
3914
- if ((this instanceof Namespace && edition) || (this.parent && this.parent.resolved)) {
3915
- this._resolveFeatures();
3962
+ if (this instanceof Root) {
3963
+ this._resolveFeaturesRecursive(this._edition);
3916
3964
  this.resolved = true;
3917
3965
  }
3918
3966
  return this;
3919
3967
  };
3920
3968
 
3969
+ /**
3970
+ * Resolves this objects editions features.
3971
+ * @param {string} edition The edition we're currently resolving for.
3972
+ * @returns {ReflectionObject} `this`
3973
+ */
3974
+ ReflectionObject.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
3975
+ return this._resolveFeatures(this._edition || edition);
3976
+ };
3977
+
3921
3978
  /**
3922
3979
  * Resolves child features from parent features
3980
+ * @param {string} edition The edition we're currently resolving for.
3923
3981
  * @returns {undefined}
3924
3982
  */
3925
- ReflectionObject.prototype._resolveFeatures = function _resolveFeatures() {
3983
+ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition) {
3926
3984
  var defaults = {};
3927
3985
 
3928
- var protoFeatures = Object.assign(Object.assign({}, this._protoFeatures), this._inferLegacyProtoFeatures(edition));
3986
+ if (!edition) {
3987
+ throw new Error("Unknown edition for " + this.fullName);
3988
+ }
3989
+
3990
+ var protoFeatures = Object.assign(this.options ? Object.assign({}, this.options.features) : {},
3991
+ this._inferLegacyProtoFeatures(edition));
3929
3992
 
3930
- var edition = this.getOption("edition");
3931
- if (this instanceof Namespace && edition) {
3993
+ if (this._edition) {
3932
3994
  // For a namespace marked with a specific edition, reset defaults.
3933
3995
  if (edition === "proto2") {
3934
3996
  defaults = Object.assign({}, proto2Defaults);
@@ -3967,7 +4029,6 @@ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures() {
3967
4029
  * in older editions.
3968
4030
  * @param {string|undefined} edition The edition this proto is on, or undefined if pre-editions
3969
4031
  * @returns {object} The feature values to override
3970
- * @abstract
3971
4032
  */
3972
4033
  ReflectionObject.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(/*edition*/) {
3973
4034
  return {};
@@ -3988,14 +4049,25 @@ ReflectionObject.prototype.getOption = function getOption(name) {
3988
4049
  * Sets an option.
3989
4050
  * @param {string} name Option name
3990
4051
  * @param {*} value Option value
3991
- * @param {boolean} [ifNotSet] Sets the option only if it isn't currently set
4052
+ * @param {boolean|undefined} [ifNotSet] Sets the option only if it isn't currently set
3992
4053
  * @returns {ReflectionObject} `this`
3993
4054
  */
3994
4055
  ReflectionObject.prototype.setOption = function setOption(name, value, ifNotSet) {
3995
- if (!ifNotSet || !this.options || this.options[name] === undefined) {
4056
+ if (!this.options)
4057
+ this.options = {};
4058
+ if (name === "features") {
4059
+ if (ifNotSet) {
4060
+ this.options.features = Object.assign(Object.assign({}, value), this.options.features || {});
4061
+ } else {
4062
+ this.options.features = Object.assign(this.options.features || {}, value);
4063
+ }
4064
+ } else if (/^features\./.test(name)) {
4065
+ util.setProperty(this.options, name, value, ifNotSet);
4066
+ } else if (!ifNotSet || this.options[name] === undefined) {
3996
4067
  if (this.getOption(name) !== value) this.resolved = false;
3997
- (this.options || (this.options = {}))[name] = value;
4068
+ this.options[name] = value;
3998
4069
  }
4070
+
3999
4071
  return this;
4000
4072
  };
4001
4073
 
@@ -4036,12 +4108,6 @@ ReflectionObject.prototype.setParsedOption = function setParsedOption(name, valu
4036
4108
  parsedOptions.push(newOpt);
4037
4109
  }
4038
4110
 
4039
-
4040
- if (isFeature) {
4041
- var features = parsedOptions.find(x => {return Object.prototype.hasOwnProperty.call(x, "features");});
4042
- this._protoFeatures = features.features || {};
4043
- }
4044
-
4045
4111
  return this;
4046
4112
  };
4047
4113
 
@@ -4070,6 +4136,19 @@ ReflectionObject.prototype.toString = function toString() {
4070
4136
  return className;
4071
4137
  };
4072
4138
 
4139
+ /**
4140
+ * Converts the edition this object is pinned to for JSON format.
4141
+ * @returns {string|undefined} The edition string for JSON representation
4142
+ */
4143
+ ReflectionObject.prototype._editionToJSON = function _editionToJSON() {
4144
+ if (!this._edition || this._edition === "proto3") {
4145
+ // Avoid emitting proto3 since we need to default to it for backwards
4146
+ // compatibility anyway.
4147
+ return undefined;
4148
+ }
4149
+ return this._edition;
4150
+ }
4151
+
4073
4152
  // Sets up cyclic dependencies (called in index-light)
4074
4153
  ReflectionObject._configure = function(Root_, Namespace_) {
4075
4154
  Root = Root_;
@@ -4389,8 +4468,21 @@ function parse(source, root, options) {
4389
4468
 
4390
4469
  var ptr = root;
4391
4470
 
4471
+ var topLevelObjects = [];
4472
+ var topLevelOptions = {};
4473
+
4392
4474
  var applyCase = options.keepCase ? function(name) { return name; } : util.camelCase;
4393
4475
 
4476
+ function resolveFileFeatures() {
4477
+ topLevelObjects.forEach(obj => {
4478
+ obj._edition = edition;
4479
+ Object.keys(topLevelOptions).forEach(opt => {
4480
+ if (obj.getOption(opt) !== undefined) return;
4481
+ obj.setOption(opt, topLevelOptions[opt]);
4482
+ });
4483
+ });
4484
+ }
4485
+
4394
4486
  /* istanbul ignore next */
4395
4487
  function illegal(token, name, insideTryCatch) {
4396
4488
  var filename = parse.filename;
@@ -4542,11 +4634,6 @@ function parse(source, root, options) {
4542
4634
 
4543
4635
  ptr = ptr.define(pkg);
4544
4636
 
4545
- var oldEdition = ptr.getOption("edition");
4546
- if (oldEdition && oldEdition !== edition) {
4547
- throw new Error("incompatible editions detected in package " + pkg + ": " + edition + " vs " + oldEdition);
4548
- }
4549
- ptr.setOption("edition", edition);
4550
4637
  skip(";");
4551
4638
  }
4552
4639
 
@@ -4580,10 +4667,6 @@ function parse(source, root, options) {
4580
4667
  if (!isProto3 && !isProto2)
4581
4668
  throw illegal(edition, "syntax");
4582
4669
 
4583
- // Syntax is needed to understand the meaning of the optional field rule
4584
- // Otherwise the meaning is ambiguous between proto2 and proto3
4585
- root.setOption("edition", edition);
4586
-
4587
4670
  skip(";");
4588
4671
  }
4589
4672
 
@@ -4598,8 +4681,6 @@ function parse(source, root, options) {
4598
4681
  if (!supportedEditions.includes(edition))
4599
4682
  throw illegal(edition, "edition");
4600
4683
 
4601
- root.setOption("edition", edition);
4602
-
4603
4684
  skip(";");
4604
4685
  }
4605
4686
 
@@ -4713,6 +4794,9 @@ function parse(source, root, options) {
4713
4794
  }
4714
4795
  });
4715
4796
  parent.add(type);
4797
+ if (parent === ptr) {
4798
+ topLevelObjects.push(type);
4799
+ }
4716
4800
  }
4717
4801
 
4718
4802
  function parseField(parent, rule, extend) {
@@ -4770,6 +4854,9 @@ function parse(source, root, options) {
4770
4854
  } else {
4771
4855
  parent.add(field);
4772
4856
  }
4857
+ if (parent === ptr) {
4858
+ topLevelObjects.push(field);
4859
+ }
4773
4860
  }
4774
4861
 
4775
4862
  function parseGroup(parent, rule) {
@@ -4907,6 +4994,9 @@ function parse(source, root, options) {
4907
4994
  }
4908
4995
  });
4909
4996
  parent.add(enm);
4997
+ if (parent === ptr) {
4998
+ topLevelObjects.push(enm);
4999
+ }
4910
5000
  }
4911
5001
 
4912
5002
  function parseEnumValue(parent, token) {
@@ -5048,6 +5138,10 @@ function parse(source, root, options) {
5048
5138
  }
5049
5139
 
5050
5140
  function setOption(parent, name, value) {
5141
+ if (ptr === parent && /^features\./.test(name)) {
5142
+ topLevelOptions[name] = value;
5143
+ return;
5144
+ }
5051
5145
  if (parent.setOption)
5052
5146
  parent.setOption(name, value);
5053
5147
  }
@@ -5086,6 +5180,9 @@ function parse(source, root, options) {
5086
5180
  throw illegal(token);
5087
5181
  });
5088
5182
  parent.add(service);
5183
+ if (parent === ptr) {
5184
+ topLevelObjects.push(service);
5185
+ }
5089
5186
  }
5090
5187
 
5091
5188
  function parseMethod(parent, token) {
@@ -5229,6 +5326,8 @@ function parse(source, root, options) {
5229
5326
  }
5230
5327
  }
5231
5328
 
5329
+ resolveFileFeatures();
5330
+
5232
5331
  parse.filename = null;
5233
5332
  return {
5234
5333
  "package" : pkg,
@@ -5760,8 +5859,8 @@ function Root(options) {
5760
5859
  */
5761
5860
  this.files = [];
5762
5861
 
5763
- // Default to proto2 if not specified.
5764
- this.setOption("edition", "proto2", true);
5862
+ // Default to proto2 if unspecified.
5863
+ this._edition = "proto2";
5765
5864
  }
5766
5865
 
5767
5866
  /**
@@ -5775,7 +5874,7 @@ Root.fromJSON = function fromJSON(json, root) {
5775
5874
  root = new Root();
5776
5875
  if (json.options)
5777
5876
  root.setOptions(json.options);
5778
- return root.addJSON(json.nested);
5877
+ return root.addJSON(json.nested).resolveAll();
5779
5878
  };
5780
5879
 
5781
5880
  /**
@@ -6369,7 +6468,10 @@ Service.fromJSON = function fromJSON(name, json) {
6369
6468
  service.add(Method.fromJSON(names[i], json.methods[names[i]]));
6370
6469
  if (json.nested)
6371
6470
  service.addJSON(json.nested);
6471
+ if (json.edition)
6472
+ service._edition = json.edition;
6372
6473
  service.comment = json.comment;
6474
+ service._defaultEdition = "proto3"; // For backwards-compatibility.
6373
6475
  return service;
6374
6476
  };
6375
6477
 
@@ -6382,6 +6484,7 @@ Service.prototype.toJSON = function toJSON(toJSONOptions) {
6382
6484
  var inherited = Namespace.prototype.toJSON.call(this, toJSONOptions);
6383
6485
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
6384
6486
  return util.toObject([
6487
+ "edition" , this._editionToJSON(),
6385
6488
  "options" , inherited && inherited.options || undefined,
6386
6489
  "methods" , Namespace.arrayToJSON(this.methodsArray, toJSONOptions) || /* istanbul ignore next */ {},
6387
6490
  "nested" , inherited && inherited.nested || undefined,
@@ -6425,6 +6528,19 @@ Service.prototype.resolveAll = function resolveAll() {
6425
6528
  return this;
6426
6529
  };
6427
6530
 
6531
+ /**
6532
+ * @override
6533
+ */
6534
+ Service.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
6535
+ var edition = this._edition || edition;
6536
+
6537
+ Namespace.prototype._resolveFeaturesRecursive.call(this, edition);
6538
+ this.methodsArray.forEach(method => {
6539
+ method._resolveFeaturesRecursive(edition);
6540
+ });
6541
+ return this;
6542
+ };
6543
+
6428
6544
  /**
6429
6545
  * @override
6430
6546
  */
@@ -7134,7 +7250,7 @@ function clearCache(type) {
7134
7250
  * @param {IType} json Message type descriptor
7135
7251
  * @returns {Type} Created message type
7136
7252
  */
7137
- Type.fromJSON = function fromJSON(name, json) {
7253
+ Type.fromJSON = function fromJSON(name, json, nested) {
7138
7254
  var type = new Type(name, json.options);
7139
7255
  type.extensions = json.extensions;
7140
7256
  type.reserved = json.reserved;
@@ -7172,6 +7288,9 @@ Type.fromJSON = function fromJSON(name, json) {
7172
7288
  type.group = true;
7173
7289
  if (json.comment)
7174
7290
  type.comment = json.comment;
7291
+ if (json.edition)
7292
+ type._edition = json.edition;
7293
+ type._defaultEdition = "proto3"; // For backwards-compatibility.
7175
7294
  return type;
7176
7295
  };
7177
7296
 
@@ -7184,6 +7303,7 @@ Type.prototype.toJSON = function toJSON(toJSONOptions) {
7184
7303
  var inherited = Namespace.prototype.toJSON.call(this, toJSONOptions);
7185
7304
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
7186
7305
  return util.toObject([
7306
+ "edition" , this._editionToJSON(),
7187
7307
  "options" , inherited && inherited.options || undefined,
7188
7308
  "oneofs" , Namespace.arrayToJSON(this.oneofsArray, toJSONOptions),
7189
7309
  "fields" , Namespace.arrayToJSON(this.fieldsArray.filter(function(obj) { return !obj.declaringField; }), toJSONOptions) || {},
@@ -7209,6 +7329,22 @@ Type.prototype.resolveAll = function resolveAll() {
7209
7329
  return this;
7210
7330
  };
7211
7331
 
7332
+ /**
7333
+ * @override
7334
+ */
7335
+ Type.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
7336
+ var edition = this._edition || edition;
7337
+
7338
+ Namespace.prototype._resolveFeaturesRecursive.call(this, edition);
7339
+ this.oneofsArray.forEach(oneof => {
7340
+ oneof._resolveFeatures(edition);
7341
+ });
7342
+ this.fieldsArray.forEach(field => {
7343
+ field._resolveFeatures(edition);
7344
+ });
7345
+ return this;
7346
+ };
7347
+
7212
7348
  /**
7213
7349
  * @override
7214
7350
  */
@@ -7861,10 +7997,10 @@ util.decorateEnum = function decorateEnum(object) {
7861
7997
  * @param {Object.<string,*>} dst Destination object
7862
7998
  * @param {string} path dot '.' delimited path of the property to set
7863
7999
  * @param {Object} value the value to set
7864
- * @param {boolean} overWrite whether or not to concatenate the values into an array or overwrite; defaults to false.
8000
+ * @param {boolean|undefined} [ifNotSet] Sets the option only if it isn't currently set
7865
8001
  * @returns {Object.<string,*>} Destination object
7866
8002
  */
7867
- util.setProperty = function setProperty(dst, path, value) {
8003
+ util.setProperty = function setProperty(dst, path, value, ifNotSet) {
7868
8004
  function setProp(dst, path, value) {
7869
8005
  var part = path.shift();
7870
8006
  if (part === "__proto__" || part === "prototype") {
@@ -7874,6 +8010,8 @@ util.setProperty = function setProperty(dst, path, value) {
7874
8010
  dst[part] = setProp(dst[part] || {}, path, value);
7875
8011
  } else {
7876
8012
  var prevValue = dst[part];
8013
+ if (prevValue && ifNotSet)
8014
+ return dst;
7877
8015
  if (prevValue)
7878
8016
  value = [].concat(prevValue).concat(value);
7879
8017
  dst[part] = value;