protobufjs 6.9.0 → 6.10.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "protobufjs",
3
- "version": "6.9.0",
3
+ "version": "6.10.0",
4
4
  "versionScheme": "~",
5
5
  "description": "Protocol Buffers for JavaScript (& TypeScript).",
6
6
  "author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
@@ -62,12 +62,12 @@
62
62
  "bundle-collapser": "^1.3.0",
63
63
  "chalk": "^4.0.0",
64
64
  "escodegen": "^1.13.0",
65
- "eslint": "^6.8.0",
66
- "espree": "^6.1.2",
65
+ "eslint": "^7.0.0",
66
+ "espree": "^7.0.0",
67
67
  "estraverse": "^5.1.0",
68
- "gh-pages": "^2.2.0",
68
+ "gh-pages": "^3.0.0",
69
69
  "git-raw-commits": "^2.0.3",
70
- "git-semver-tags": "^3.0.1",
70
+ "git-semver-tags": "^4.0.0",
71
71
  "glob": "^7.1.6",
72
72
  "google-protobuf": "^3.11.3",
73
73
  "gulp": "^4.0.2",
@@ -81,8 +81,8 @@
81
81
  "nyc": "^15.0.0",
82
82
  "reflect-metadata": "^0.1.13",
83
83
  "semver": "^7.1.2",
84
- "tape": "^4.13.0",
85
- "tmp": "^0.1.0",
84
+ "tape": "^5.0.0",
85
+ "tmp": "^0.2.0",
86
86
  "tslint": "^5.20.1",
87
87
  "typescript": "^3.7.5",
88
88
  "uglify-js": "^3.7.7",
package/src/decoder.js CHANGED
@@ -19,7 +19,7 @@ function decoder(mtype) {
19
19
  var gen = util.codegen(["r", "l"], mtype.name + "$decode")
20
20
  ("if(!(r instanceof Reader))")
21
21
  ("r=Reader.create(r)")
22
- ("var c=l===undefined?r.len:r.pos+l,m=new this.ctor" + (mtype.fieldsArray.filter(function(field) { return field.map; }).length ? ",k" : ""))
22
+ ("var c=l===undefined?r.len:r.pos+l,m=new this.ctor" + (mtype.fieldsArray.filter(function(field) { return field.map; }).length ? ",k,value" : ""))
23
23
  ("while(r.pos<c){")
24
24
  ("var t=r.uint32()");
25
25
  if (mtype.group) gen
@@ -37,22 +37,44 @@ function decoder(mtype) {
37
37
 
38
38
  // Map fields
39
39
  if (field.map) { gen
40
- ("r.skip().pos++") // assumes id 1 + key wireType
41
40
  ("if(%s===util.emptyObject)", ref)
42
41
  ("%s={}", ref)
43
- ("k=r.%s()", field.keyType)
44
- ("r.pos++"); // assumes id 2 + value wireType
45
- if (types.long[field.keyType] !== undefined) {
46
- if (types.basic[type] === undefined) gen
47
- ("%s[typeof k===\"object\"?util.longToHash(k):k]=types[%i].decode(r,r.uint32())", ref, i); // can't be groups
48
- else gen
49
- ("%s[typeof k===\"object\"?util.longToHash(k):k]=r.%s()", ref, type);
50
- } else {
51
- if (types.basic[type] === undefined) gen
52
- ("%s[k]=types[%i].decode(r,r.uint32())", ref, i); // can't be groups
53
- else gen
54
- ("%s[k]=r.%s()", ref, type);
55
- }
42
+ ("var c2 = r.uint32()+r.pos");
43
+
44
+ if (types.defaults[field.keyType] !== undefined) gen
45
+ ("k=%j", types.defaults[field.keyType]);
46
+ else gen
47
+ ("k=null");
48
+
49
+ if (types.defaults[type] !== undefined) gen
50
+ ("value=%j", types.defaults[type]);
51
+ else gen
52
+ ("value=null");
53
+
54
+ gen
55
+ ("while(r.pos<c2){")
56
+ ("var tag2=r.uint32()")
57
+ ("switch(tag2>>>3){")
58
+ ("case 1: k=r.%s(); break", field.keyType)
59
+ ("case 2:");
60
+
61
+ if (types.basic[type] === undefined) gen
62
+ ("value=types[%i].decode(r,r.uint32())", i); // can't be groups
63
+ else gen
64
+ ("value=r.%s()", type);
65
+
66
+ gen
67
+ ("break")
68
+ ("default:")
69
+ ("r.skipType(tag2&7)")
70
+ ("break")
71
+ ("}")
72
+ ("}");
73
+
74
+ if (types.long[field.keyType] !== undefined) gen
75
+ ("%s[typeof k===\"object\"?util.longToHash(k):k]=value", ref);
76
+ else gen
77
+ ("%s[k]=value", ref);
56
78
 
57
79
  // Repeated fields
58
80
  } else if (field.repeated) { gen
package/src/object.js CHANGED
@@ -29,6 +29,12 @@ function ReflectionObject(name, options) {
29
29
  */
30
30
  this.options = options; // toJSON
31
31
 
32
+ /**
33
+ * Parsed Options.
34
+ * @type {Array.<Object.<string,*>>|undefined}
35
+ */
36
+ this.parsedOptions = null;
37
+
32
38
  /**
33
39
  * Unique name within its namespace.
34
40
  * @type {string}
@@ -169,6 +175,43 @@ ReflectionObject.prototype.setOption = function setOption(name, value, ifNotSet)
169
175
  return this;
170
176
  };
171
177
 
178
+ /**
179
+ * Sets a parsed option.
180
+ * @param {string} name parsed Option name
181
+ * @param {*} value Option value
182
+ * @param {string} propName dot '.' delimited full path of property within the option to set. if undefined\empty, will add a new option with that value
183
+ * @returns {ReflectionObject} `this`
184
+ */
185
+ ReflectionObject.prototype.setParsedOption = function setParsedOption(name, value, propName) {
186
+ if (!this.parsedOptions) {
187
+ this.parsedOptions = [];
188
+ }
189
+ var parsedOptions = this.parsedOptions;
190
+ if (propName) {
191
+ // If setting a sub property of an option then try to merge it
192
+ // with an existing option
193
+ var opt = parsedOptions.find(function (opt) {
194
+ return Object.prototype.hasOwnProperty.call(opt, name);
195
+ });
196
+ if (opt) {
197
+ // If we found an existing option - just merge the property value
198
+ var newValue = opt[name];
199
+ util.setProperty(newValue, propName, value);
200
+ } else {
201
+ // otherwise, create a new option, set it's property and add it to the list
202
+ opt = {};
203
+ opt[name] = util.setProperty({}, propName, value);
204
+ parsedOptions.push(opt);
205
+ }
206
+ } else {
207
+ // Always create a new option when setting the value of the option itself
208
+ var newOpt = {};
209
+ newOpt[name] = value;
210
+ parsedOptions.push(newOpt);
211
+ }
212
+ return this;
213
+ };
214
+
172
215
  /**
173
216
  * Sets multiple options.
174
217
  * @param {Object.<string,*>} options Options to set
package/src/parse.js CHANGED
@@ -42,6 +42,7 @@ var base10Re = /^[1-9][0-9]*$/,
42
42
  * @interface IParseOptions
43
43
  * @property {boolean} [keepCase=false] Keeps field casing instead of converting to camel case
44
44
  * @property {boolean} [alternateCommentMode=false] Recognize double-slash comments in addition to doc-block comments.
45
+ * @property {boolean} [preferTrailingComment=false] Use trailing comment when both leading comment and trailing comment exist.
45
46
  */
46
47
 
47
48
  /**
@@ -68,6 +69,7 @@ function parse(source, root, options) {
68
69
  if (!options)
69
70
  options = parse.defaults;
70
71
 
72
+ var preferTrailingComment = options.preferTrailingComment || false;
71
73
  var tn = tokenize(source, options.alternateCommentMode || false),
72
74
  next = tn.next,
73
75
  push = tn.push,
@@ -291,8 +293,8 @@ function parse(source, root, options) {
291
293
  if (fnElse)
292
294
  fnElse();
293
295
  skip(";");
294
- if (obj && typeof obj.comment !== "string")
295
- obj.comment = cmnt(trailingLine); // try line-type comment if no block
296
+ if (obj && (typeof obj.comment !== "string" || preferTrailingComment))
297
+ obj.comment = cmnt(trailingLine) || obj.comment; // try line-type comment
296
298
  }
297
299
  }
298
300
 
@@ -540,39 +542,58 @@ function parse(source, root, options) {
540
542
  throw illegal(token, "name");
541
543
 
542
544
  var name = token;
545
+ var option = name;
546
+ var propName;
547
+
543
548
  if (isCustom) {
544
549
  skip(")");
545
550
  name = "(" + name + ")";
551
+ option = name;
546
552
  token = peek();
547
553
  if (fqTypeRefRe.test(token)) {
554
+ propName = token.substr(1); //remove '.' before property name
548
555
  name += token;
549
556
  next();
550
557
  }
551
558
  }
552
559
  skip("=");
553
- parseOptionValue(parent, name);
560
+ var optionValue = parseOptionValue(parent, name);
561
+ setParsedOption(parent, option, optionValue, propName);
554
562
  }
555
563
 
556
564
  function parseOptionValue(parent, name) {
557
565
  if (skip("{", true)) { // { a: "foo" b { c: "bar" } }
558
- do {
566
+ var result = {};
567
+ while (!skip("}", true)) {
559
568
  /* istanbul ignore if */
560
569
  if (!nameRe.test(token = next()))
561
570
  throw illegal(token, "name");
562
571
 
572
+ var value;
573
+ var propName = token;
563
574
  if (peek() === "{")
564
- parseOptionValue(parent, name + "." + token);
575
+ value = parseOptionValue(parent, name + "." + token);
565
576
  else {
566
577
  skip(":");
567
578
  if (peek() === "{")
568
- parseOptionValue(parent, name + "." + token);
569
- else
570
- setOption(parent, name + "." + token, readValue(true));
579
+ value = parseOptionValue(parent, name + "." + token);
580
+ else {
581
+ value = readValue(true);
582
+ setOption(parent, name + "." + token, value);
583
+ }
571
584
  }
585
+ var prevValue = result[propName];
586
+ if (prevValue)
587
+ value = [].concat(prevValue).concat(value);
588
+ result[propName] = value;
572
589
  skip(",", true);
573
- } while (!skip("}", true));
574
- } else
575
- setOption(parent, name, readValue(true));
590
+ }
591
+ return result;
592
+ }
593
+
594
+ var simpleValue = readValue(true);
595
+ setOption(parent, name, simpleValue);
596
+ return simpleValue;
576
597
  // Does not enforce a delimiter to be universal
577
598
  }
578
599
 
@@ -581,6 +602,11 @@ function parse(source, root, options) {
581
602
  parent.setOption(name, value);
582
603
  }
583
604
 
605
+ function setParsedOption(parent, name, value, propName) {
606
+ if (parent.setParsedOption)
607
+ parent.setParsedOption(name, value, propName);
608
+ }
609
+
584
610
  function parseInlineOptions(parent) {
585
611
  if (skip("[", true)) {
586
612
  do {
package/src/root.js CHANGED
@@ -61,6 +61,16 @@ Root.fromJSON = function fromJSON(json, root) {
61
61
  */
62
62
  Root.prototype.resolvePath = util.path.resolve;
63
63
 
64
+ /**
65
+ * Fetch content from file path or url
66
+ * This method exists so you can override it with your own logic.
67
+ * @function
68
+ * @param {string} path File path or url
69
+ * @param {FetchCallback} callback Callback function
70
+ * @returns {undefined}
71
+ */
72
+ Root.prototype.fetch = util.fetch;
73
+
64
74
  // A symbol-like function to safely signal synchronous loading
65
75
  /* istanbul ignore next */
66
76
  function SYNC() {} // eslint-disable-line no-empty-function
@@ -168,7 +178,7 @@ Root.prototype.load = function load(filename, options, callback) {
168
178
  process(filename, source);
169
179
  } else {
170
180
  ++queued;
171
- util.fetch(filename, function(err, source) {
181
+ self.fetch(filename, function(err, source) {
172
182
  --queued;
173
183
  /* istanbul ignore if */
174
184
  if (!callback)
package/src/tokenize.js CHANGED
@@ -106,7 +106,8 @@ function tokenize(source, alternateCommentMode) {
106
106
  commentType = null,
107
107
  commentText = null,
108
108
  commentLine = 0,
109
- commentLineEmpty = false;
109
+ commentLineEmpty = false,
110
+ commentIsLeading = false;
110
111
 
111
112
  var stack = [];
112
113
 
@@ -154,13 +155,15 @@ function tokenize(source, alternateCommentMode) {
154
155
  * Sets the current comment text.
155
156
  * @param {number} start Start offset
156
157
  * @param {number} end End offset
158
+ * @param {boolean} isLeading set if a leading comment
157
159
  * @returns {undefined}
158
160
  * @inner
159
161
  */
160
- function setComment(start, end) {
162
+ function setComment(start, end, isLeading) {
161
163
  commentType = source.charAt(start++);
162
164
  commentLine = line;
163
165
  commentLineEmpty = false;
166
+ commentIsLeading = isLeading;
164
167
  var lookback;
165
168
  if (alternateCommentMode) {
166
169
  lookback = 2; // alternate comment parsing: "//" or "/*"
@@ -222,14 +225,17 @@ function tokenize(source, alternateCommentMode) {
222
225
  prev,
223
226
  curr,
224
227
  start,
225
- isDoc;
228
+ isDoc,
229
+ isLeadingComment = offset === 0;
226
230
  do {
227
231
  if (offset === length)
228
232
  return null;
229
233
  repeat = false;
230
234
  while (whitespaceRe.test(curr = charAt(offset))) {
231
- if (curr === "\n")
235
+ if (curr === "\n") {
236
+ isLeadingComment = true;
232
237
  ++line;
238
+ }
233
239
  if (++offset === length)
234
240
  return null;
235
241
  }
@@ -250,7 +256,7 @@ function tokenize(source, alternateCommentMode) {
250
256
  }
251
257
  ++offset;
252
258
  if (isDoc) {
253
- setComment(start, offset - 1);
259
+ setComment(start, offset - 1, isLeadingComment);
254
260
  }
255
261
  ++line;
256
262
  repeat = true;
@@ -271,7 +277,7 @@ function tokenize(source, alternateCommentMode) {
271
277
  offset = Math.min(length, findEndOfLine(offset) + 1);
272
278
  }
273
279
  if (isDoc) {
274
- setComment(start, offset);
280
+ setComment(start, offset, isLeadingComment);
275
281
  }
276
282
  line++;
277
283
  repeat = true;
@@ -292,7 +298,7 @@ function tokenize(source, alternateCommentMode) {
292
298
  } while (prev !== "*" || curr !== "/");
293
299
  ++offset;
294
300
  if (isDoc) {
295
- setComment(start, offset - 2);
301
+ setComment(start, offset - 2, isLeadingComment);
296
302
  }
297
303
  repeat = true;
298
304
  } else {
@@ -370,7 +376,7 @@ function tokenize(source, alternateCommentMode) {
370
376
  var ret = null;
371
377
  if (trailingLine === undefined) {
372
378
  if (commentLine === line - 1 && (alternateCommentMode || commentType === "*" || commentLineEmpty)) {
373
- ret = commentText;
379
+ ret = commentIsLeading ? commentText : null;
374
380
  }
375
381
  } else {
376
382
  /* istanbul ignore else */
@@ -378,7 +384,7 @@ function tokenize(source, alternateCommentMode) {
378
384
  peek();
379
385
  }
380
386
  if (commentLine === trailingLine && !commentLineEmpty && (alternateCommentMode || commentType === "/")) {
381
- ret = commentText;
387
+ ret = commentIsLeading ? null : commentText;
382
388
  }
383
389
  }
384
390
  return ret;
@@ -26,8 +26,8 @@ util.pool = require("@protobufjs/pool");
26
26
  util.LongBits = require("./longbits");
27
27
 
28
28
  // global object reference
29
- util.global = typeof window !== "undefined" && window
30
- || typeof global !== "undefined" && global
29
+ util.global = typeof global !== "undefined" && Object.prototype.toString.call(global) === "[object global]" && global
30
+ || typeof window !== "undefined" && window
31
31
  || typeof self !== "undefined" && self
32
32
  || this; // eslint-disable-line no-invalid-this
33
33
 
package/src/util.js CHANGED
@@ -165,6 +165,37 @@ util.decorateEnum = function decorateEnum(object) {
165
165
  return enm;
166
166
  };
167
167
 
168
+
169
+ /**
170
+ * Sets the value of a property by property path. If a value already exists, it is turned to an array
171
+ * @param {Object.<string,*>} dst Destination object
172
+ * @param {string} path dot '.' delimited path of the property to set
173
+ * @param {Object} value the value to set
174
+ * @returns {Object.<string,*>} Destination object
175
+ */
176
+ util.setProperty = function setProperty(dst, path, value) {
177
+ function setProp(dst, path, value) {
178
+ var part = path.shift();
179
+ if (path.length > 0) {
180
+ dst[part] = setProp(dst[part] || {}, path, value);
181
+ } else {
182
+ var prevValue = dst[part];
183
+ if (prevValue)
184
+ value = [].concat(prevValue).concat(value);
185
+ dst[part] = value;
186
+ }
187
+ return dst;
188
+ }
189
+
190
+ if (typeof dst !== "object")
191
+ throw TypeError("dst must be an object");
192
+ if (!path)
193
+ throw TypeError("path must be specified");
194
+
195
+ path = path.split(".");
196
+ return setProp(dst, path, value);
197
+ };
198
+
168
199
  /**
169
200
  * Decorator root (TypeScript).
170
201
  * @name util.decorateRoot
package/src/wrappers.js CHANGED
@@ -42,15 +42,20 @@ wrappers[".google.protobuf.Any"] = {
42
42
 
43
43
  // unwrap value type if mapped
44
44
  if (object && object["@type"]) {
45
- var type = this.lookup(object["@type"]);
45
+ // Only use fully qualified type name after the last '/'
46
+ var name = object["@type"].substring(object["@type"].lastIndexOf("/") + 1);
47
+ var type = this.lookup(name);
46
48
  /* istanbul ignore else */
47
49
  if (type) {
48
50
  // type_url does not accept leading "."
49
51
  var type_url = object["@type"].charAt(0) === "." ?
50
52
  object["@type"].substr(1) : object["@type"];
51
53
  // type_url prefix is optional, but path seperator is required
54
+ if (type_url.indexOf("/") === -1) {
55
+ type_url = "/" + type_url;
56
+ }
52
57
  return this.create({
53
- type_url: "/" + type_url,
58
+ type_url: type_url,
54
59
  value: type.encode(type.fromObject(object)).finish()
55
60
  });
56
61
  }
@@ -61,10 +66,17 @@ wrappers[".google.protobuf.Any"] = {
61
66
 
62
67
  toObject: function(message, options) {
63
68
 
69
+ // Default prefix
70
+ var googleApi = "type.googleapis.com/";
71
+ var prefix = "";
72
+ var name = "";
73
+
64
74
  // decode value if requested and unmapped
65
75
  if (options && options.json && message.type_url && message.value) {
66
76
  // Only use fully qualified type name after the last '/'
67
- var name = message.type_url.substring(message.type_url.lastIndexOf("/") + 1);
77
+ name = message.type_url.substring(message.type_url.lastIndexOf("/") + 1);
78
+ // Separate the prefix used
79
+ prefix = message.type_url.substring(0, message.type_url.lastIndexOf("/") + 1);
68
80
  var type = this.lookup(name);
69
81
  /* istanbul ignore else */
70
82
  if (type)
@@ -74,7 +86,14 @@ wrappers[".google.protobuf.Any"] = {
74
86
  // wrap value if unmapped
75
87
  if (!(message instanceof this.ctor) && message instanceof Message) {
76
88
  var object = message.$type.toObject(message, options);
77
- object["@type"] = message.$type.fullName;
89
+ var messageName = message.$type.fullName[0] === "." ?
90
+ message.$type.fullName.substr(1) : message.$type.fullName;
91
+ // Default to type.googleapis.com prefix if no prefix is used
92
+ if (prefix === "") {
93
+ prefix = googleApi;
94
+ }
95
+ name = prefix + messageName;
96
+ object["@type"] = name;
78
97
  return object;
79
98
  }
80
99