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.
package/index.d.ts CHANGED
@@ -188,12 +188,6 @@ export class Enum extends ReflectionObject {
188
188
  /** Reserved ranges, if any. */
189
189
  public reserved: (number[]|string)[];
190
190
 
191
- /**
192
- * Resolves value features
193
- * @returns `this`
194
- */
195
- public resolve(): Enum;
196
-
197
191
  /**
198
192
  * Constructs an enum from an enum descriptor.
199
193
  * @param name Enum name
@@ -906,11 +900,17 @@ export abstract class ReflectionObject {
906
900
  /** Unique name within its namespace. */
907
901
  public name: string;
908
902
 
909
- /** Resolved Features. */
910
- public _features: any;
903
+ /** The edition specified for this object. Only relevant for top-level objects. */
904
+ public _edition: string;
911
905
 
912
- /** Unresolved Features. */
913
- public _protoFeatures: any;
906
+ /**
907
+ * The default edition to use for this object if none is specified. For legacy reasons,
908
+ * this is proto2 except in the JSON parsing case where it was proto3.
909
+ */
910
+ public _defaultEdition: string;
911
+
912
+ /** Resolved Features. */
913
+ public _features: object;
914
914
 
915
915
  /** Parent namespace. */
916
916
  public parent: (Namespace|null);
@@ -954,8 +954,18 @@ export abstract class ReflectionObject {
954
954
  */
955
955
  public resolve(): ReflectionObject;
956
956
 
957
- /** Resolves child features from parent features */
958
- public _resolveFeatures(): void;
957
+ /**
958
+ * Resolves this objects editions features.
959
+ * @param edition The edition we're currently resolving for.
960
+ * @returns `this`
961
+ */
962
+ public _resolveFeaturesRecursive(edition: string): ReflectionObject;
963
+
964
+ /**
965
+ * Resolves child features from parent features
966
+ * @param edition The edition we're currently resolving for.
967
+ */
968
+ public _resolveFeatures(edition: string): void;
959
969
 
960
970
  /**
961
971
  * Infers features from legacy syntax that may have been specified differently.
@@ -979,7 +989,7 @@ export abstract class ReflectionObject {
979
989
  * @param [ifNotSet] Sets the option only if it isn't currently set
980
990
  * @returns `this`
981
991
  */
982
- public setOption(name: string, value: any, ifNotSet?: boolean): ReflectionObject;
992
+ public setOption(name: string, value: any, ifNotSet?: (boolean|undefined)): ReflectionObject;
983
993
 
984
994
  /**
985
995
  * Sets a parsed option.
@@ -1003,6 +1013,12 @@ export abstract class ReflectionObject {
1003
1013
  * @returns Class name[, space, full name]
1004
1014
  */
1005
1015
  public toString(): string;
1016
+
1017
+ /**
1018
+ * Converts the edition this object is pinned to for JSON format.
1019
+ * @returns The edition string for JSON representation
1020
+ */
1021
+ public _editionToJSON(): (string|undefined);
1006
1022
  }
1007
1023
 
1008
1024
  /** Reflected oneof. */
@@ -2244,10 +2260,10 @@ export namespace util {
2244
2260
  * @param dst Destination object
2245
2261
  * @param path dot '.' delimited path of the property to set
2246
2262
  * @param value the value to set
2247
- * @param overWrite whether or not to concatenate the values into an array or overwrite; defaults to false.
2263
+ * @param [ifNotSet] Sets the option only if it isn't currently set
2248
2264
  * @returns Destination object
2249
2265
  */
2250
- function setProperty(dst: { [k: string]: any }, path: string, value: object, overWrite: boolean): { [k: string]: any };
2266
+ function setProperty(dst: { [k: string]: any }, path: string, value: object, ifNotSet?: (boolean|undefined)): { [k: string]: any };
2251
2267
 
2252
2268
  /** Decorator root (TypeScript). */
2253
2269
  let decorateRoot: Root;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "protobufjs",
3
- "version": "8.0.3-experimental",
3
+ "version": "8.0.4-experimental",
4
4
  "versionScheme": "~",
5
5
  "description": "Protocol Buffers for JavaScript (& TypeScript).",
6
6
  "author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
package/src/enum.js CHANGED
@@ -85,21 +85,20 @@ function Enum(name, values, options, comment, comments, valuesOptions) {
85
85
  }
86
86
 
87
87
  /**
88
- * Resolves value features
89
- * @returns {Enum} `this`
88
+ * @override
90
89
  */
91
- Enum.prototype.resolve = function resolve() {
92
- ReflectionObject.prototype.resolve.call(this);
90
+ Enum.prototype._resolveFeatures = function _resolveFeatures(edition) {
91
+ var edition = this._edition || edition;
92
+ ReflectionObject.prototype._resolveFeatures.call(this, edition);
93
93
 
94
- for (var key of Object.keys(this._valuesProtoFeatures)) {
94
+ Object.keys(this._valuesProtoFeatures).forEach(key => {
95
95
  var parentFeaturesCopy = Object.assign({}, this._features);
96
96
  this._valuesFeatures[key] = Object.assign(parentFeaturesCopy, this._valuesProtoFeatures[key] || {});
97
- }
97
+ });
98
98
 
99
99
  return this;
100
100
  };
101
101
 
102
-
103
102
  /**
104
103
  * Enum descriptor.
105
104
  * @interface IEnum
@@ -117,6 +116,9 @@ Enum.prototype.resolve = function resolve() {
117
116
  Enum.fromJSON = function fromJSON(name, json) {
118
117
  var enm = new Enum(name, json.values, json.options, json.comment, json.comments);
119
118
  enm.reserved = json.reserved;
119
+ if (json.edition)
120
+ enm._edition = json.edition;
121
+ enm._defaultEdition = "proto3"; // For backwards-compatibility.
120
122
  return enm;
121
123
  };
122
124
 
@@ -128,6 +130,7 @@ Enum.fromJSON = function fromJSON(name, json) {
128
130
  Enum.prototype.toJSON = function toJSON(toJSONOptions) {
129
131
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
130
132
  return util.toObject([
133
+ "edition" , this._editionToJSON(),
131
134
  "options" , this.options,
132
135
  "valuesOptions" , this.valuesOptions,
133
136
  "values" , this.values,
package/src/field.js CHANGED
@@ -35,7 +35,11 @@ var ruleRe = /^required|optional|repeated$/;
35
35
  * @throws {TypeError} If arguments are invalid
36
36
  */
37
37
  Field.fromJSON = function fromJSON(name, json) {
38
- return new Field(name, json.id, json.type, json.rule, json.extend, json.options, json.comment);
38
+ var field = new Field(name, json.id, json.type, json.rule, json.extend, json.options, json.comment);
39
+ if (json.edition)
40
+ field._edition = json.edition;
41
+ field._defaultEdition = "proto3"; // For backwards-compatibility.
42
+ return field;
39
43
  };
40
44
 
41
45
  /**
@@ -276,6 +280,7 @@ Field.prototype.setOption = function setOption(name, value, ifNotSet) {
276
280
  Field.prototype.toJSON = function toJSON(toJSONOptions) {
277
281
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
278
282
  return util.toObject([
283
+ "edition" , this._editionToJSON(),
279
284
  "rule" , this.rule !== "optional" && this.rule || undefined,
280
285
  "type" , this.type,
281
286
  "id" , this.id,
@@ -360,9 +365,12 @@ Field.prototype.resolve = function resolve() {
360
365
  * @returns {object} The feature values to override
361
366
  */
362
367
  Field.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(edition) {
363
- if (edition) return {};
368
+ if (edition !== "proto2" && edition !== "proto3") {
369
+ return;
370
+ }
364
371
 
365
372
  var features = {};
373
+ this.resolve();
366
374
  if (this.rule === "required") {
367
375
  features.field_presence = "LEGACY_REQUIRED";
368
376
  }
@@ -377,6 +385,13 @@ Field.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(e
377
385
  return features;
378
386
  };
379
387
 
388
+ /**
389
+ * @override
390
+ */
391
+ Field.prototype._resolveFeatures = function _resolveFeatures(edition) {
392
+ return ReflectionObject.prototype._resolveFeatures.call(this, this._edition || edition);
393
+ };
394
+
380
395
  /**
381
396
  * Decorator function as returned by {@link Field.d} and {@link MapField.d} (TypeScript).
382
397
  * @typedef FieldDecorator
package/src/namespace.js CHANGED
@@ -240,6 +240,15 @@ Namespace.prototype.add = function add(object) {
240
240
  }
241
241
  }
242
242
  this.nested[object.name] = object;
243
+
244
+ if (!(this instanceof Type || this instanceof Service || this instanceof Enum || this instanceof Field)) {
245
+ // This is a package or a root namespace.
246
+ if (!object._edition) {
247
+ // Make sure that some edition is set if it hasn't already been specified.
248
+ object._edition = object._defaultEdition;
249
+ }
250
+ }
251
+
243
252
  object.onAdd(this);
244
253
  return clearCache(this);
245
254
  };
@@ -311,6 +320,19 @@ Namespace.prototype.resolveAll = function resolveAll() {
311
320
  return this;
312
321
  };
313
322
 
323
+ /**
324
+ * @override
325
+ */
326
+ Namespace.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
327
+ var edition = this._edition || edition;
328
+
329
+ ReflectionObject.prototype._resolveFeaturesRecursive.call(this, edition);
330
+ this.nestedArray.forEach(nested => {
331
+ nested._resolveFeaturesRecursive(edition);
332
+ });
333
+ return this;
334
+ };
335
+
314
336
  /**
315
337
  * Recursively looks up the reflection object matching the specified path in the scope of this namespace.
316
338
  * @param {string|string[]} path Path to look up
package/src/object.js CHANGED
@@ -49,14 +49,23 @@ function ReflectionObject(name, options) {
49
49
  this.name = name;
50
50
 
51
51
  /**
52
- * Resolved Features.
52
+ * The edition specified for this object. Only relevant for top-level objects.
53
+ * @type {string}
53
54
  */
54
- this._features = {};
55
+ this._edition = null;
56
+
57
+ /**
58
+ * The default edition to use for this object if none is specified. For legacy reasons,
59
+ * this is proto2 except in the JSON parsing case where it was proto3.
60
+ * @type {string}
61
+ */
62
+ this._defaultEdition = "proto2";
55
63
 
56
64
  /**
57
- * Unresolved Features.
65
+ * Resolved Features.
66
+ * @type {object}
58
67
  */
59
- this._protoFeatures = null;
68
+ this._features = {};
60
69
 
61
70
  /**
62
71
  * Parent namespace.
@@ -163,25 +172,38 @@ ReflectionObject.prototype.onRemove = function onRemove(parent) {
163
172
  ReflectionObject.prototype.resolve = function resolve() {
164
173
  if (this.resolved)
165
174
  return this;
166
- var edition = this.getOption("edition");
167
- if ((this instanceof Namespace && edition) || (this.parent && this.parent.resolved)) {
168
- this._resolveFeatures();
175
+ if (this instanceof Root) {
176
+ this._resolveFeaturesRecursive(this._edition);
169
177
  this.resolved = true;
170
178
  }
171
179
  return this;
172
180
  };
173
181
 
182
+ /**
183
+ * Resolves this objects editions features.
184
+ * @param {string} edition The edition we're currently resolving for.
185
+ * @returns {ReflectionObject} `this`
186
+ */
187
+ ReflectionObject.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
188
+ return this._resolveFeatures(this._edition || edition);
189
+ };
190
+
174
191
  /**
175
192
  * Resolves child features from parent features
193
+ * @param {string} edition The edition we're currently resolving for.
176
194
  * @returns {undefined}
177
195
  */
178
- ReflectionObject.prototype._resolveFeatures = function _resolveFeatures() {
196
+ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition) {
179
197
  var defaults = {};
180
198
 
181
- var protoFeatures = Object.assign(Object.assign({}, this._protoFeatures), this._inferLegacyProtoFeatures(edition));
199
+ if (!edition) {
200
+ throw new Error("Unknown edition for " + this.fullName);
201
+ }
202
+
203
+ var protoFeatures = Object.assign(this.options ? Object.assign({}, this.options.features) : {},
204
+ this._inferLegacyProtoFeatures(edition));
182
205
 
183
- var edition = this.getOption("edition");
184
- if (this instanceof Namespace && edition) {
206
+ if (this._edition) {
185
207
  // For a namespace marked with a specific edition, reset defaults.
186
208
  if (edition === "proto2") {
187
209
  defaults = Object.assign({}, proto2Defaults);
@@ -220,7 +242,6 @@ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures() {
220
242
  * in older editions.
221
243
  * @param {string|undefined} edition The edition this proto is on, or undefined if pre-editions
222
244
  * @returns {object} The feature values to override
223
- * @abstract
224
245
  */
225
246
  ReflectionObject.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(/*edition*/) {
226
247
  return {};
@@ -241,14 +262,25 @@ ReflectionObject.prototype.getOption = function getOption(name) {
241
262
  * Sets an option.
242
263
  * @param {string} name Option name
243
264
  * @param {*} value Option value
244
- * @param {boolean} [ifNotSet] Sets the option only if it isn't currently set
265
+ * @param {boolean|undefined} [ifNotSet] Sets the option only if it isn't currently set
245
266
  * @returns {ReflectionObject} `this`
246
267
  */
247
268
  ReflectionObject.prototype.setOption = function setOption(name, value, ifNotSet) {
248
- if (!ifNotSet || !this.options || this.options[name] === undefined) {
269
+ if (!this.options)
270
+ this.options = {};
271
+ if (name === "features") {
272
+ if (ifNotSet) {
273
+ this.options.features = Object.assign(Object.assign({}, value), this.options.features || {});
274
+ } else {
275
+ this.options.features = Object.assign(this.options.features || {}, value);
276
+ }
277
+ } else if (/^features\./.test(name)) {
278
+ util.setProperty(this.options, name, value, ifNotSet);
279
+ } else if (!ifNotSet || this.options[name] === undefined) {
249
280
  if (this.getOption(name) !== value) this.resolved = false;
250
- (this.options || (this.options = {}))[name] = value;
281
+ this.options[name] = value;
251
282
  }
283
+
252
284
  return this;
253
285
  };
254
286
 
@@ -289,12 +321,6 @@ ReflectionObject.prototype.setParsedOption = function setParsedOption(name, valu
289
321
  parsedOptions.push(newOpt);
290
322
  }
291
323
 
292
-
293
- if (isFeature) {
294
- var features = parsedOptions.find(x => {return Object.prototype.hasOwnProperty.call(x, "features");});
295
- this._protoFeatures = features.features || {};
296
- }
297
-
298
324
  return this;
299
325
  };
300
326
 
@@ -323,6 +349,19 @@ ReflectionObject.prototype.toString = function toString() {
323
349
  return className;
324
350
  };
325
351
 
352
+ /**
353
+ * Converts the edition this object is pinned to for JSON format.
354
+ * @returns {string|undefined} The edition string for JSON representation
355
+ */
356
+ ReflectionObject.prototype._editionToJSON = function _editionToJSON() {
357
+ if (!this._edition || this._edition === "proto3") {
358
+ // Avoid emitting proto3 since we need to default to it for backwards
359
+ // compatibility anyway.
360
+ return undefined;
361
+ }
362
+ return this._edition;
363
+ }
364
+
326
365
  // Sets up cyclic dependencies (called in index-light)
327
366
  ReflectionObject._configure = function(Root_, Namespace_) {
328
367
  Root = Root_;
package/src/parse.js CHANGED
@@ -86,8 +86,21 @@ function parse(source, root, options) {
86
86
 
87
87
  var ptr = root;
88
88
 
89
+ var topLevelObjects = [];
90
+ var topLevelOptions = {};
91
+
89
92
  var applyCase = options.keepCase ? function(name) { return name; } : util.camelCase;
90
93
 
94
+ function resolveFileFeatures() {
95
+ topLevelObjects.forEach(obj => {
96
+ obj._edition = edition;
97
+ Object.keys(topLevelOptions).forEach(opt => {
98
+ if (obj.getOption(opt) !== undefined) return;
99
+ obj.setOption(opt, topLevelOptions[opt]);
100
+ });
101
+ });
102
+ }
103
+
91
104
  /* istanbul ignore next */
92
105
  function illegal(token, name, insideTryCatch) {
93
106
  var filename = parse.filename;
@@ -239,11 +252,6 @@ function parse(source, root, options) {
239
252
 
240
253
  ptr = ptr.define(pkg);
241
254
 
242
- var oldEdition = ptr.getOption("edition");
243
- if (oldEdition && oldEdition !== edition) {
244
- throw new Error("incompatible editions detected in package " + pkg + ": " + edition + " vs " + oldEdition);
245
- }
246
- ptr.setOption("edition", edition);
247
255
  skip(";");
248
256
  }
249
257
 
@@ -277,10 +285,6 @@ function parse(source, root, options) {
277
285
  if (!isProto3 && !isProto2)
278
286
  throw illegal(edition, "syntax");
279
287
 
280
- // Syntax is needed to understand the meaning of the optional field rule
281
- // Otherwise the meaning is ambiguous between proto2 and proto3
282
- root.setOption("edition", edition);
283
-
284
288
  skip(";");
285
289
  }
286
290
 
@@ -295,8 +299,6 @@ function parse(source, root, options) {
295
299
  if (!supportedEditions.includes(edition))
296
300
  throw illegal(edition, "edition");
297
301
 
298
- root.setOption("edition", edition);
299
-
300
302
  skip(";");
301
303
  }
302
304
 
@@ -410,6 +412,9 @@ function parse(source, root, options) {
410
412
  }
411
413
  });
412
414
  parent.add(type);
415
+ if (parent === ptr) {
416
+ topLevelObjects.push(type);
417
+ }
413
418
  }
414
419
 
415
420
  function parseField(parent, rule, extend) {
@@ -467,6 +472,9 @@ function parse(source, root, options) {
467
472
  } else {
468
473
  parent.add(field);
469
474
  }
475
+ if (parent === ptr) {
476
+ topLevelObjects.push(field);
477
+ }
470
478
  }
471
479
 
472
480
  function parseGroup(parent, rule) {
@@ -604,6 +612,9 @@ function parse(source, root, options) {
604
612
  }
605
613
  });
606
614
  parent.add(enm);
615
+ if (parent === ptr) {
616
+ topLevelObjects.push(enm);
617
+ }
607
618
  }
608
619
 
609
620
  function parseEnumValue(parent, token) {
@@ -745,6 +756,10 @@ function parse(source, root, options) {
745
756
  }
746
757
 
747
758
  function setOption(parent, name, value) {
759
+ if (ptr === parent && /^features\./.test(name)) {
760
+ topLevelOptions[name] = value;
761
+ return;
762
+ }
748
763
  if (parent.setOption)
749
764
  parent.setOption(name, value);
750
765
  }
@@ -783,6 +798,9 @@ function parse(source, root, options) {
783
798
  throw illegal(token);
784
799
  });
785
800
  parent.add(service);
801
+ if (parent === ptr) {
802
+ topLevelObjects.push(service);
803
+ }
786
804
  }
787
805
 
788
806
  function parseMethod(parent, token) {
@@ -926,6 +944,8 @@ function parse(source, root, options) {
926
944
  }
927
945
  }
928
946
 
947
+ resolveFileFeatures();
948
+
929
949
  parse.filename = null;
930
950
  return {
931
951
  "package" : pkg,
package/src/root.js CHANGED
@@ -36,8 +36,8 @@ function Root(options) {
36
36
  */
37
37
  this.files = [];
38
38
 
39
- // Default to proto2 if not specified.
40
- this.setOption("edition", "proto2", true);
39
+ // Default to proto2 if unspecified.
40
+ this._edition = "proto2";
41
41
  }
42
42
 
43
43
  /**
@@ -51,7 +51,7 @@ Root.fromJSON = function fromJSON(json, root) {
51
51
  root = new Root();
52
52
  if (json.options)
53
53
  root.setOptions(json.options);
54
- return root.addJSON(json.nested);
54
+ return root.addJSON(json.nested).resolveAll();
55
55
  };
56
56
 
57
57
  /**
package/src/service.js CHANGED
@@ -57,7 +57,10 @@ Service.fromJSON = function fromJSON(name, json) {
57
57
  service.add(Method.fromJSON(names[i], json.methods[names[i]]));
58
58
  if (json.nested)
59
59
  service.addJSON(json.nested);
60
+ if (json.edition)
61
+ service._edition = json.edition;
60
62
  service.comment = json.comment;
63
+ service._defaultEdition = "proto3"; // For backwards-compatibility.
61
64
  return service;
62
65
  };
63
66
 
@@ -70,6 +73,7 @@ Service.prototype.toJSON = function toJSON(toJSONOptions) {
70
73
  var inherited = Namespace.prototype.toJSON.call(this, toJSONOptions);
71
74
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
72
75
  return util.toObject([
76
+ "edition" , this._editionToJSON(),
73
77
  "options" , inherited && inherited.options || undefined,
74
78
  "methods" , Namespace.arrayToJSON(this.methodsArray, toJSONOptions) || /* istanbul ignore next */ {},
75
79
  "nested" , inherited && inherited.nested || undefined,
@@ -113,6 +117,19 @@ Service.prototype.resolveAll = function resolveAll() {
113
117
  return this;
114
118
  };
115
119
 
120
+ /**
121
+ * @override
122
+ */
123
+ Service.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
124
+ var edition = this._edition || edition;
125
+
126
+ Namespace.prototype._resolveFeaturesRecursive.call(this, edition);
127
+ this.methodsArray.forEach(method => {
128
+ method._resolveFeaturesRecursive(edition);
129
+ });
130
+ return this;
131
+ };
132
+
116
133
  /**
117
134
  * @override
118
135
  */
package/src/type.js CHANGED
@@ -234,7 +234,7 @@ function clearCache(type) {
234
234
  * @param {IType} json Message type descriptor
235
235
  * @returns {Type} Created message type
236
236
  */
237
- Type.fromJSON = function fromJSON(name, json) {
237
+ Type.fromJSON = function fromJSON(name, json, nested) {
238
238
  var type = new Type(name, json.options);
239
239
  type.extensions = json.extensions;
240
240
  type.reserved = json.reserved;
@@ -272,6 +272,9 @@ Type.fromJSON = function fromJSON(name, json) {
272
272
  type.group = true;
273
273
  if (json.comment)
274
274
  type.comment = json.comment;
275
+ if (json.edition)
276
+ type._edition = json.edition;
277
+ type._defaultEdition = "proto3"; // For backwards-compatibility.
275
278
  return type;
276
279
  };
277
280
 
@@ -284,6 +287,7 @@ Type.prototype.toJSON = function toJSON(toJSONOptions) {
284
287
  var inherited = Namespace.prototype.toJSON.call(this, toJSONOptions);
285
288
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
286
289
  return util.toObject([
290
+ "edition" , this._editionToJSON(),
287
291
  "options" , inherited && inherited.options || undefined,
288
292
  "oneofs" , Namespace.arrayToJSON(this.oneofsArray, toJSONOptions),
289
293
  "fields" , Namespace.arrayToJSON(this.fieldsArray.filter(function(obj) { return !obj.declaringField; }), toJSONOptions) || {},
@@ -309,6 +313,22 @@ Type.prototype.resolveAll = function resolveAll() {
309
313
  return this;
310
314
  };
311
315
 
316
+ /**
317
+ * @override
318
+ */
319
+ Type.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
320
+ var edition = this._edition || edition;
321
+
322
+ Namespace.prototype._resolveFeaturesRecursive.call(this, edition);
323
+ this.oneofsArray.forEach(oneof => {
324
+ oneof._resolveFeatures(edition);
325
+ });
326
+ this.fieldsArray.forEach(field => {
327
+ field._resolveFeatures(edition);
328
+ });
329
+ return this;
330
+ };
331
+
312
332
  /**
313
333
  * @override
314
334
  */
package/src/util.js CHANGED
@@ -171,10 +171,10 @@ util.decorateEnum = function decorateEnum(object) {
171
171
  * @param {Object.<string,*>} dst Destination object
172
172
  * @param {string} path dot '.' delimited path of the property to set
173
173
  * @param {Object} value the value to set
174
- * @param {boolean} overWrite whether or not to concatenate the values into an array or overwrite; defaults to false.
174
+ * @param {boolean|undefined} [ifNotSet] Sets the option only if it isn't currently set
175
175
  * @returns {Object.<string,*>} Destination object
176
176
  */
177
- util.setProperty = function setProperty(dst, path, value) {
177
+ util.setProperty = function setProperty(dst, path, value, ifNotSet) {
178
178
  function setProp(dst, path, value) {
179
179
  var part = path.shift();
180
180
  if (part === "__proto__" || part === "prototype") {
@@ -184,6 +184,8 @@ util.setProperty = function setProperty(dst, path, value) {
184
184
  dst[part] = setProp(dst[part] || {}, path, value);
185
185
  } else {
186
186
  var prevValue = dst[part];
187
+ if (prevValue && ifNotSet)
188
+ return dst;
187
189
  if (prevValue)
188
190
  value = [].concat(prevValue).concat(value);
189
191
  dst[part] = value;