protobufjs 7.5.0 → 7.5.1

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
@@ -750,6 +750,9 @@ export abstract class NamespaceBase extends ReflectionObject {
750
750
  /** Nested objects by name. */
751
751
  public nested?: { [k: string]: ReflectionObject };
752
752
 
753
+ /** Whether or not objects contained in this namespace need feature resolution. */
754
+ protected _needsRecursiveFeatureResolution: boolean;
755
+
753
756
  /** Nested objects of this namespace as an array for iteration. */
754
757
  public readonly nestedArray: ReflectionObject[];
755
758
 
@@ -909,6 +912,9 @@ export abstract class ReflectionObject {
909
912
  /** Resolved Features. */
910
913
  public _features: object;
911
914
 
915
+ /** Whether or not features have been resolved. */
916
+ public _featuresResolved: boolean;
917
+
912
918
  /** Parent namespace. */
913
919
  public parent: (Namespace|null);
914
920
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "protobufjs",
3
- "version": "7.5.0",
3
+ "version": "7.5.1",
4
4
  "versionScheme": "~",
5
5
  "description": "Protocol Buffers for JavaScript (& TypeScript).",
6
6
  "author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
@@ -33,7 +33,9 @@
33
33
  "build:bundle": "gulp --gulpfile scripts/gulpfile.js",
34
34
  "build:types": "node cli/bin/pbts --main --global protobuf --out index.d.ts src/ lib/aspromise/index.js lib/base64/index.js lib/codegen/index.js lib/eventemitter/index.js lib/float/index.js lib/fetch/index.js lib/inquire/index.js lib/path/index.js lib/pool/index.js lib/utf8/index.js",
35
35
  "changelog": "node scripts/changelog -w",
36
- "coverage": "nyc tape -r ./lib/tape-adapter tests/*.js tests/node/*.js",
36
+ "coverage": "npm run coverage:test && npm run coverage:report",
37
+ "coverage:test": "nyc --silent tape -r ./lib/tape-adapter tests/*.js tests/node/*.js",
38
+ "coverage:report": "nyc report --reporter=lcov --reporter=text",
37
39
  "docs": "jsdoc -c config/jsdoc.json -R README.md --verbose --pedantic",
38
40
  "lint": "npm run lint:sources && npm run lint:types",
39
41
  "lint:sources": "eslint \"**/*.js\" -c config/eslint.json",
package/src/field.js CHANGED
@@ -370,12 +370,18 @@ Field.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(e
370
370
  }
371
371
 
372
372
  var features = {};
373
- this.resolve();
373
+
374
374
  if (this.rule === "required") {
375
375
  features.field_presence = "LEGACY_REQUIRED";
376
376
  }
377
- if (this.resolvedType instanceof Type && this.resolvedType.group) {
378
- features.message_encoding = "DELIMITED";
377
+ if (this.parent && types.defaults[this.type] === undefined) {
378
+ // We can't use resolvedType because types may not have been resolved yet. However,
379
+ // legacy groups are always in the same scope as the field so we don't have to do a
380
+ // full scan of the tree.
381
+ var type = this.parent.get(this.type.split(".").pop());
382
+ if (type && type instanceof Type && type.group) {
383
+ features.message_encoding = "DELIMITED";
384
+ }
379
385
  }
380
386
  if (this.getOption("packed") === true) {
381
387
  features.repeated_field_encoding = "PACKED";
package/src/namespace.js CHANGED
@@ -108,10 +108,33 @@ function Namespace(name, options) {
108
108
  * @private
109
109
  */
110
110
  this._nestedArray = null;
111
+
112
+ /**
113
+ * Cache lookup calls for any objects contains anywhere under this namespace.
114
+ * This drastically speeds up resolve for large cross-linked protos where the same
115
+ * types are looked up repeatedly.
116
+ * @type {Object.<string,ReflectionObject|null>}
117
+ * @private
118
+ */
119
+ this._lookupCache = {};
120
+
121
+ /**
122
+ * Whether or not objects contained in this namespace need feature resolution.
123
+ * @type {boolean}
124
+ * @protected
125
+ */
126
+ this._needsRecursiveFeatureResolution = true;
111
127
  }
112
128
 
113
129
  function clearCache(namespace) {
114
130
  namespace._nestedArray = null;
131
+ namespace._lookupCache = {};
132
+
133
+ // Also clear parent caches, since they include nested lookups.
134
+ var parent = namespace;
135
+ while(parent = parent.parent) {
136
+ parent._lookupCache = {};
137
+ }
115
138
  return namespace;
116
139
  }
117
140
 
@@ -249,6 +272,14 @@ Namespace.prototype.add = function add(object) {
249
272
  }
250
273
  }
251
274
 
275
+ this._needsRecursiveFeatureResolution = true;
276
+
277
+ // Also clear parent caches, since they need to recurse down.
278
+ var parent = this;
279
+ while(parent = parent.parent) {
280
+ parent._needsRecursiveFeatureResolution = true;
281
+ }
282
+
252
283
  object.onAdd(this);
253
284
  return clearCache(this);
254
285
  };
@@ -324,6 +355,9 @@ Namespace.prototype.resolveAll = function resolveAll() {
324
355
  * @override
325
356
  */
326
357
  Namespace.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
358
+ if (!this._needsRecursiveFeatureResolution) return this;
359
+ this._needsRecursiveFeatureResolution = false;
360
+
327
361
  edition = this._edition || edition;
328
362
 
329
363
  ReflectionObject.prototype._resolveFeaturesRecursive.call(this, edition);
@@ -341,7 +375,6 @@ Namespace.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursi
341
375
  * @returns {ReflectionObject|null} Looked up object or `null` if none could be found
342
376
  */
343
377
  Namespace.prototype.lookup = function lookup(path, filterTypes, parentAlreadyChecked) {
344
-
345
378
  /* istanbul ignore next */
346
379
  if (typeof filterTypes === "boolean") {
347
380
  parentAlreadyChecked = filterTypes;
@@ -360,25 +393,48 @@ Namespace.prototype.lookup = function lookup(path, filterTypes, parentAlreadyChe
360
393
  if (path[0] === "")
361
394
  return this.root.lookup(path.slice(1), filterTypes);
362
395
 
396
+ var found = this._lookupImpl(path);
397
+ if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) {
398
+ return found;
399
+ }
400
+
401
+ // If there hasn't been a match, try again at the parent
402
+ if (this.parent === null || parentAlreadyChecked)
403
+ return null;
404
+ return this.parent.lookup(path, filterTypes);
405
+ };
406
+
407
+ /**
408
+ * Internal helper for lookup that handles searching just at this namespace and below along with caching.
409
+ * @param {string[]} path Path to look up
410
+ * @returns {ReflectionObject|null} Looked up object or `null` if none could be found
411
+ * @private
412
+ */
413
+ Namespace.prototype._lookupImpl = function lookup(path) {
414
+ var flatPath = path.join(".");
415
+ if(Object.prototype.hasOwnProperty.call(this._lookupCache, flatPath)) {
416
+ return this._lookupCache[flatPath];
417
+ }
418
+
363
419
  // Test if the first part matches any nested object, and if so, traverse if path contains more
364
420
  var found = this.get(path[0]);
421
+ var exact = null;
365
422
  if (found) {
366
423
  if (path.length === 1) {
367
- if (!filterTypes || filterTypes.indexOf(found.constructor) > -1)
368
- return found;
369
- } else if (found instanceof Namespace && (found = found.lookup(path.slice(1), filterTypes, true)))
370
- return found;
424
+ exact = found;
425
+ } else if (found instanceof Namespace && (found = found._lookupImpl(path.slice(1))))
426
+ exact = found;
371
427
 
372
428
  // Otherwise try each nested namespace
373
- } else
429
+ } else {
374
430
  for (var i = 0; i < this.nestedArray.length; ++i)
375
- if (this._nestedArray[i] instanceof Namespace && (found = this._nestedArray[i].lookup(path, filterTypes, true)))
376
- return found;
431
+ if (this._nestedArray[i] instanceof Namespace && (found = this._nestedArray[i]._lookupImpl(path)))
432
+ exact = found;
433
+ }
377
434
 
378
- // If there hasn't been a match, try again at the parent
379
- if (this.parent === null || parentAlreadyChecked)
380
- return null;
381
- return this.parent.lookup(path, filterTypes);
435
+ // Set this even when null, so that when we walk up the tree we can quickly bail on repeated checks back down.
436
+ this._lookupCache[flatPath] = exact;
437
+ return exact;
382
438
  };
383
439
 
384
440
  /**
package/src/object.js CHANGED
@@ -67,6 +67,12 @@ function ReflectionObject(name, options) {
67
67
  */
68
68
  this._features = {};
69
69
 
70
+ /**
71
+ * Whether or not features have been resolved.
72
+ * @type {boolean}
73
+ */
74
+ this._featuresResolved = false;
75
+
70
76
  /**
71
77
  * Parent namespace.
72
78
  * @type {Namespace|null}
@@ -172,10 +178,8 @@ ReflectionObject.prototype.onRemove = function onRemove(parent) {
172
178
  ReflectionObject.prototype.resolve = function resolve() {
173
179
  if (this.resolved)
174
180
  return this;
175
- if (this instanceof Root) {
176
- this._resolveFeaturesRecursive(this._edition);
177
- this.resolved = true;
178
- }
181
+ if (this.root instanceof Root)
182
+ this.resolved = true; // only if part of a root
179
183
  return this;
180
184
  };
181
185
 
@@ -194,6 +198,10 @@ ReflectionObject.prototype._resolveFeaturesRecursive = function _resolveFeatures
194
198
  * @returns {undefined}
195
199
  */
196
200
  ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition) {
201
+ if (this._featuresResolved) {
202
+ return;
203
+ }
204
+
197
205
  var defaults = {};
198
206
 
199
207
  /* istanbul ignore if */
@@ -217,6 +225,7 @@ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition)
217
225
  throw new Error("Unknown edition: " + edition);
218
226
  }
219
227
  this._features = Object.assign(defaults, protoFeatures || {});
228
+ this._featuresResolved = true;
220
229
  return;
221
230
  }
222
231
 
@@ -238,6 +247,7 @@ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition)
238
247
  // Sister fields should have the same features as their extensions.
239
248
  this.extensionField._features = this._features;
240
249
  }
250
+ this._featuresResolved = true;
241
251
  };
242
252
 
243
253
  /**
package/src/parse.js CHANGED
@@ -523,6 +523,10 @@ function parse(source, root, options) {
523
523
  parseEnum(type, token);
524
524
  break;
525
525
 
526
+ case "reserved":
527
+ readRanges(type.reserved || (type.reserved = []), true);
528
+ break;
529
+
526
530
  /* istanbul ignore next */
527
531
  default:
528
532
  throw illegal(token); // there are no groups with proto3 semantics
package/src/root.js CHANGED
@@ -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).resolveAll();
54
+ return root.addJSON(json.nested)._resolveFeaturesRecursive();
55
55
  };
56
56
 
57
57
  /**
@@ -99,6 +99,9 @@ Root.prototype.load = function load(filename, options, callback) {
99
99
 
100
100
  // Finishes loading by calling the callback (exactly once)
101
101
  function finish(err, root) {
102
+ if (root) {
103
+ root._resolveFeaturesRecursive();
104
+ }
102
105
  /* istanbul ignore if */
103
106
  if (!callback) {
104
107
  return;
@@ -108,9 +111,6 @@ Root.prototype.load = function load(filename, options, callback) {
108
111
  }
109
112
  var cb = callback;
110
113
  callback = null;
111
- if (root) {
112
- root.resolveAll();
113
- }
114
114
  cb(err, root);
115
115
  }
116
116
 
@@ -218,8 +218,8 @@ Root.prototype.load = function load(filename, options, callback) {
218
218
  for (var i = 0, resolved; i < filename.length; ++i)
219
219
  if (resolved = self.resolvePath("", filename[i]))
220
220
  fetch(resolved);
221
- self.resolveAll();
222
221
  if (sync) {
222
+ self._resolveFeaturesRecursive();
223
223
  return self;
224
224
  }
225
225
  if (!queued) {
@@ -272,6 +272,7 @@ Root.prototype.resolveAll = function resolveAll() {
272
272
  throw Error("unresolvable extensions: " + this.deferred.map(function(field) {
273
273
  return "'extend " + field.extend + "' in " + field.parent.fullName;
274
274
  }).join(", "));
275
+ this._resolveFeaturesRecursive(this._edition);
275
276
  return Namespace.prototype.resolveAll.call(this);
276
277
  };
277
278
 
package/src/service.js CHANGED
@@ -121,6 +121,8 @@ Service.prototype.resolveAll = function resolveAll() {
121
121
  * @override
122
122
  */
123
123
  Service.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
124
+ if (!this._needsRecursiveFeatureResolution) return this;
125
+
124
126
  edition = this._edition || edition;
125
127
 
126
128
  Namespace.prototype._resolveFeaturesRecursive.call(this, edition);
package/src/type.js CHANGED
@@ -317,6 +317,8 @@ Type.prototype.resolveAll = function resolveAll() {
317
317
  * @override
318
318
  */
319
319
  Type.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
320
+ if (!this._needsRecursiveFeatureResolution) return this;
321
+
320
322
  edition = this._edition || edition;
321
323
 
322
324
  Namespace.prototype._resolveFeaturesRecursive.call(this, edition);