protobufjs 7.4.0 → 8.0.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.
package/src/parse.js CHANGED
@@ -13,6 +13,7 @@ var tokenize = require("./tokenize"),
13
13
  Enum = require("./enum"),
14
14
  Service = require("./service"),
15
15
  Method = require("./method"),
16
+ ReflectionObject = require("./object"),
16
17
  types = require("./types"),
17
18
  util = require("./util");
18
19
 
@@ -24,8 +25,7 @@ var base10Re = /^[1-9][0-9]*$/,
24
25
  base8NegRe = /^-?0[0-7]+$/,
25
26
  numberRe = /^(?![eE])[0-9]*(?:\.[0-9]*)?(?:[eE][+-]?[0-9]+)?$/,
26
27
  nameRe = /^[a-zA-Z_][a-zA-Z_0-9]*$/,
27
- typeRefRe = /^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*$/,
28
- fqTypeRefRe = /^(?:\.[a-zA-Z_][a-zA-Z_0-9]*)+$/;
28
+ typeRefRe = /^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*$/;
29
29
 
30
30
  /**
31
31
  * Result object returned from {@link parse}.
@@ -82,6 +82,7 @@ function parse(source, root, options) {
82
82
  imports,
83
83
  weakImports,
84
84
  syntax,
85
+ edition = false,
85
86
  isProto3 = false;
86
87
 
87
88
  var ptr = root;
@@ -126,7 +127,6 @@ function parse(source, root, options) {
126
127
  try {
127
128
  return parseNumber(token, /* insideTryCatch */ true);
128
129
  } catch (e) {
129
-
130
130
  /* istanbul ignore else */
131
131
  if (acceptTypeRef && typeRefRe.test(token))
132
132
  return token;
@@ -141,8 +141,17 @@ function parse(source, root, options) {
141
141
  do {
142
142
  if (acceptStrings && ((token = peek()) === "\"" || token === "'"))
143
143
  target.push(readString());
144
- else
145
- target.push([ start = parseId(next()), skip("to", true) ? parseId(next()) : start ]);
144
+ else {
145
+ try {
146
+ target.push([ start = parseId(next()), skip("to", true) ? parseId(next()) : start ]);
147
+ } catch (err) {
148
+ if (typeRefRe.test(token) && edition) {
149
+ target.push(token);
150
+ } else {
151
+ throw err;
152
+ }
153
+ }
154
+ }
146
155
  } while (skip(",", true));
147
156
  var dummy = {options: undefined};
148
157
  dummy.setOption = function(name, value) {
@@ -270,6 +279,21 @@ function parse(source, root, options) {
270
279
  skip(";");
271
280
  }
272
281
 
282
+ function parseEdition() {
283
+ skip("=");
284
+ edition = readString();
285
+ const supportedEditions = ["2023"];
286
+
287
+ /* istanbul ignore if */
288
+ if (!supportedEditions.includes(edition))
289
+ throw illegal(edition, "edition");
290
+
291
+ root.setOption("edition", edition);
292
+
293
+ skip(";");
294
+ }
295
+
296
+
273
297
  function parseCommon(parent, token) {
274
298
  switch (token) {
275
299
 
@@ -337,6 +361,9 @@ function parse(source, root, options) {
337
361
  break;
338
362
 
339
363
  case "required":
364
+ if (edition)
365
+ throw illegal(token);
366
+ /* eslint-disable no-fallthrough */
340
367
  case "repeated":
341
368
  parseField(type, token);
342
369
  break;
@@ -345,6 +372,8 @@ function parse(source, root, options) {
345
372
  /* istanbul ignore if */
346
373
  if (isProto3) {
347
374
  parseField(type, "proto3_optional");
375
+ } else if (edition) {
376
+ throw illegal(token);
348
377
  } else {
349
378
  parseField(type, "optional");
350
379
  }
@@ -364,8 +393,9 @@ function parse(source, root, options) {
364
393
 
365
394
  default:
366
395
  /* istanbul ignore if */
367
- if (!isProto3 || !typeRefRe.test(token))
396
+ if (!isProto3 && !edition || !typeRefRe.test(token)) {
368
397
  throw illegal(token);
398
+ }
369
399
 
370
400
  push(token);
371
401
  parseField(type, "optional");
@@ -399,6 +429,7 @@ function parse(source, root, options) {
399
429
  var name = next();
400
430
 
401
431
  /* istanbul ignore if */
432
+
402
433
  if (!nameRe.test(name))
403
434
  throw illegal(name, "name");
404
435
 
@@ -406,6 +437,7 @@ function parse(source, root, options) {
406
437
  skip("=");
407
438
 
408
439
  var field = new Field(name, parseId(next()), type, rule, extend);
440
+
409
441
  ifBlock(field, function parseField_block(token) {
410
442
 
411
443
  /* istanbul ignore else */
@@ -428,12 +460,6 @@ function parse(source, root, options) {
428
460
  } else {
429
461
  parent.add(field);
430
462
  }
431
-
432
- // JSON defaults to packed=true if not set so we have to set packed=false explicity when
433
- // parsing proto2 descriptors without the option, where applicable. This must be done for
434
- // all known packable types and anything that could be an enum (= is not a basic type).
435
- if (!isProto3 && field.repeated && (types.packed[type] !== undefined || types.basic[type] === undefined))
436
- field.setOption("packed", false, /* ifNotSet */ true);
437
463
  }
438
464
 
439
465
  function parseGroup(parent, rule) {
@@ -459,7 +485,6 @@ function parse(source, root, options) {
459
485
  parseOption(type, token);
460
486
  skip(";");
461
487
  break;
462
-
463
488
  case "required":
464
489
  case "repeated":
465
490
  parseField(type, token);
@@ -588,8 +613,17 @@ function parse(source, root, options) {
588
613
  dummy.setOption = function(name, value) {
589
614
  if (this.options === undefined)
590
615
  this.options = {};
616
+
591
617
  this.options[name] = value;
592
618
  };
619
+ dummy.setParsedOption = function(name, value, propName) {
620
+ // In order to not change existing behavior, only calling
621
+ // this for features
622
+ if (/^features$/.test(name)) {
623
+ return ReflectionObject.prototype.setParsedOption.call(dummy, name, value, propName);
624
+ }
625
+ return undefined;
626
+ };
593
627
  ifBlock(dummy, function parseEnumValue_block(token) {
594
628
 
595
629
  /* istanbul ignore else */
@@ -602,34 +636,42 @@ function parse(source, root, options) {
602
636
  }, function parseEnumValue_line() {
603
637
  parseInlineOptions(dummy); // skip
604
638
  });
605
- parent.add(token, value, dummy.comment, dummy.options);
639
+ parent.add(token, value, dummy.comment, dummy.parsedOptions || dummy.options);
606
640
  }
607
641
 
608
642
  function parseOption(parent, token) {
609
- var isCustom = skip("(", true);
610
-
611
- /* istanbul ignore if */
612
- if (!typeRefRe.test(token = next()))
613
- throw illegal(token, "name");
614
-
615
- var name = token;
616
- var option = name;
617
- var propName;
643
+ var option;
644
+ var propName;
645
+ var isOption = true;
646
+ if (token === "option") {
647
+ token = next();
648
+ }
618
649
 
619
- if (isCustom) {
620
- skip(")");
621
- name = "(" + name + ")";
622
- option = name;
623
- token = peek();
624
- if (fqTypeRefRe.test(token)) {
625
- propName = token.slice(1); //remove '.' before property name
626
- name += token;
627
- next();
650
+ while (token !== "=") {
651
+ if (token === "(") {
652
+ var parensValue = next();
653
+ skip(")");
654
+ token = "(" + parensValue + ")";
655
+ }
656
+ if (isOption) {
657
+ isOption = false;
658
+ if (token.includes(".") && !token.includes("(")) {
659
+ var tokens = token.split(".");
660
+ option = tokens[0] + ".";
661
+ token = tokens[1];
662
+ continue;
663
+ }
664
+ option = token;
665
+ } else {
666
+ propName = propName ? propName += token : token;
667
+ }
668
+ token = next();
628
669
  }
629
- }
630
- skip("=");
631
- var optionValue = parseOptionValue(parent, name);
632
- setParsedOption(parent, option, optionValue, propName);
670
+ var name = propName ? option.concat(propName) : option;
671
+ var optionValue = parseOptionValue(parent, name);
672
+ propName = propName && propName[0] === "." ? propName.slice(1) : propName;
673
+ option = option && option[option.length - 1] === "." ? option.slice(0, -1) : option;
674
+ setParsedOption(parent, option, optionValue, propName);
633
675
  }
634
676
 
635
677
  function parseOptionValue(parent, name) {
@@ -651,12 +693,12 @@ function parse(source, root, options) {
651
693
 
652
694
  skip(":", true);
653
695
 
654
- if (peek() === "{")
655
- value = parseOptionValue(parent, name + "." + token);
656
- else if (peek() === "[") {
696
+ if (peek() === "{") {
657
697
  // option (my_option) = {
658
698
  // repeated_value: [ "foo", "bar" ]
659
699
  // };
700
+ value = parseOptionValue(parent, name + "." + token);
701
+ } else if (peek() === "[") {
660
702
  value = [];
661
703
  var lastValue;
662
704
  if (skip("[", true)) {
@@ -723,8 +765,9 @@ function parse(source, root, options) {
723
765
 
724
766
  var service = new Service(token);
725
767
  ifBlock(service, function parseService_block(token) {
726
- if (parseCommon(service, token))
768
+ if (parseCommon(service, token)) {
727
769
  return;
770
+ }
728
771
 
729
772
  /* istanbul ignore else */
730
773
  if (token === "rpc")
@@ -811,7 +854,7 @@ function parse(source, root, options) {
811
854
 
812
855
  default:
813
856
  /* istanbul ignore if */
814
- if (!isProto3 || !typeRefRe.test(token))
857
+ if (!isProto3 && !edition || !typeRefRe.test(token))
815
858
  throw illegal(token);
816
859
  push(token);
817
860
  parseField(parent, "optional", reference);
@@ -851,10 +894,16 @@ function parse(source, root, options) {
851
894
  parseSyntax();
852
895
  break;
853
896
 
854
- case "option":
897
+ case "edition":
898
+ /* istanbul ignore if */
899
+ if (!head)
900
+ throw illegal(token);
901
+ parseEdition();
902
+ break;
855
903
 
904
+ case "option":
856
905
  parseOption(ptr, token);
857
- skip(";");
906
+ skip(";", true);
858
907
  break;
859
908
 
860
909
  default:
package/src/root.js CHANGED
@@ -39,7 +39,7 @@ function Root(options) {
39
39
 
40
40
  /**
41
41
  * Loads a namespace descriptor into a root namespace.
42
- * @param {INamespace} json Nameespace descriptor
42
+ * @param {INamespace} json Namespace descriptor
43
43
  * @param {Root} [root] Root namespace, defaults to create a new one if omitted
44
44
  * @returns {Root} Root namespace
45
45
  */
@@ -88,20 +88,26 @@ Root.prototype.load = function load(filename, options, callback) {
88
88
  options = undefined;
89
89
  }
90
90
  var self = this;
91
- if (!callback)
91
+ if (!callback) {
92
92
  return util.asPromise(load, self, filename, options);
93
+ }
93
94
 
94
95
  var sync = callback === SYNC; // undocumented
95
96
 
96
97
  // Finishes loading by calling the callback (exactly once)
97
98
  function finish(err, root) {
98
99
  /* istanbul ignore if */
99
- if (!callback)
100
+ if (!callback) {
100
101
  return;
101
- if (sync)
102
+ }
103
+ if (sync) {
102
104
  throw err;
105
+ }
103
106
  var cb = callback;
104
107
  callback = null;
108
+ if (root) {
109
+ root.resolveAll();
110
+ }
105
111
  cb(err, root);
106
112
  }
107
113
 
@@ -139,8 +145,9 @@ Root.prototype.load = function load(filename, options, callback) {
139
145
  } catch (err) {
140
146
  finish(err);
141
147
  }
142
- if (!sync && !queued)
148
+ if (!sync && !queued) {
143
149
  finish(null, self); // only once anyway
150
+ }
144
151
  }
145
152
 
146
153
  // Fetches a single file
@@ -148,15 +155,16 @@ Root.prototype.load = function load(filename, options, callback) {
148
155
  filename = getBundledFileName(filename) || filename;
149
156
 
150
157
  // Skip if already loaded / attempted
151
- if (self.files.indexOf(filename) > -1)
158
+ if (self.files.indexOf(filename) > -1) {
152
159
  return;
160
+ }
153
161
  self.files.push(filename);
154
162
 
155
163
  // Shortcut bundled definitions
156
164
  if (filename in common) {
157
- if (sync)
165
+ if (sync) {
158
166
  process(filename, common[filename]);
159
- else {
167
+ } else {
160
168
  ++queued;
161
169
  setTimeout(function() {
162
170
  --queued;
@@ -182,8 +190,9 @@ Root.prototype.load = function load(filename, options, callback) {
182
190
  self.fetch(filename, function(err, source) {
183
191
  --queued;
184
192
  /* istanbul ignore if */
185
- if (!callback)
193
+ if (!callback) {
186
194
  return; // terminated meanwhile
195
+ }
187
196
  if (err) {
188
197
  /* istanbul ignore else */
189
198
  if (!weak)
@@ -200,17 +209,21 @@ Root.prototype.load = function load(filename, options, callback) {
200
209
 
201
210
  // Assembling the root namespace doesn't require working type
202
211
  // references anymore, so we can load everything in parallel
203
- if (util.isString(filename))
212
+ if (util.isString(filename)) {
204
213
  filename = [ filename ];
214
+ }
205
215
  for (var i = 0, resolved; i < filename.length; ++i)
206
216
  if (resolved = self.resolvePath("", filename[i]))
207
217
  fetch(resolved);
208
-
209
- if (sync)
218
+ self.resolveAll();
219
+ if (sync) {
210
220
  return self;
211
- if (!queued)
221
+ }
222
+ if (!queued) {
212
223
  finish(null, self);
213
- return undefined;
224
+ }
225
+
226
+ return self;
214
227
  };
215
228
  // function load(filename:string, options:IParseOptions, callback:LoadCallback):undefined
216
229
 
package/src/service.js CHANGED
@@ -106,10 +106,11 @@ Service.prototype.get = function get(name) {
106
106
  * @override
107
107
  */
108
108
  Service.prototype.resolveAll = function resolveAll() {
109
+ Namespace.prototype.resolve.call(this);
109
110
  var methods = this.methodsArray;
110
111
  for (var i = 0; i < methods.length; ++i)
111
112
  methods[i].resolve();
112
- return Namespace.prototype.resolve.call(this);
113
+ return this;
113
114
  };
114
115
 
115
116
  /**
package/src/type.js CHANGED
@@ -299,13 +299,14 @@ Type.prototype.toJSON = function toJSON(toJSONOptions) {
299
299
  * @override
300
300
  */
301
301
  Type.prototype.resolveAll = function resolveAll() {
302
- var fields = this.fieldsArray, i = 0;
303
- while (i < fields.length)
304
- fields[i++].resolve();
302
+ Namespace.prototype.resolveAll.call(this);
305
303
  var oneofs = this.oneofsArray; i = 0;
306
304
  while (i < oneofs.length)
307
305
  oneofs[i++].resolve();
308
- return Namespace.prototype.resolveAll.call(this);
306
+ var fields = this.fieldsArray, i = 0;
307
+ while (i < fields.length)
308
+ fields[i++].resolve();
309
+ return this;
309
310
  };
310
311
 
311
312
  /**
package/src/util.js CHANGED
@@ -171,6 +171,7 @@ 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
175
  * @returns {Object.<string,*>} Destination object
175
176
  */
176
177
  util.setProperty = function setProperty(dst, path, value) {