protobufjs 8.4.0 → 8.4.2

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/ext/descriptor.js CHANGED
@@ -268,13 +268,13 @@ Type.fromDescriptor = function fromDescriptor(descriptor, edition, nested, depth
268
268
  /* Extension ranges */ if (descriptor.extensionRange && descriptor.extensionRange.length) {
269
269
  type.extensions = [];
270
270
  for (i = 0; i < descriptor.extensionRange.length; ++i)
271
- type.extensions.push([ descriptor.extensionRange[i].start, descriptor.extensionRange[i].end ]);
271
+ type.extensions.push([ descriptor.extensionRange[i].start, descriptor.extensionRange[i].end - 1 ]);
272
272
  }
273
273
  /* Reserved... */ if (descriptor.reservedRange && descriptor.reservedRange.length || descriptor.reservedName && descriptor.reservedName.length) {
274
274
  type.reserved = [];
275
275
  /* Ranges */ if (descriptor.reservedRange)
276
276
  for (i = 0; i < descriptor.reservedRange.length; ++i)
277
- type.reserved.push([ descriptor.reservedRange[i].start, descriptor.reservedRange[i].end ]);
277
+ type.reserved.push([ descriptor.reservedRange[i].start, descriptor.reservedRange[i].end - 1 ]);
278
278
  /* Names */ if (descriptor.reservedName)
279
279
  for (i = 0; i < descriptor.reservedName.length; ++i)
280
280
  type.reserved.push(descriptor.reservedName[i]);
@@ -324,13 +324,13 @@ Type.prototype.toDescriptor = function toDescriptor(edition) {
324
324
  }
325
325
  /* Extension ranges */ if (this.extensions)
326
326
  for (i = 0; i < this.extensions.length; ++i)
327
- descriptor.extensionRange.push(exports.DescriptorProto.ExtensionRange.create({ start: this.extensions[i][0], end: this.extensions[i][1] }));
327
+ descriptor.extensionRange.push(exports.DescriptorProto.ExtensionRange.create({ start: this.extensions[i][0], end: this.extensions[i][1] + 1 }));
328
328
  /* Reserved... */ if (this.reserved)
329
329
  for (i = 0; i < this.reserved.length; ++i)
330
330
  /* Names */ if (typeof this.reserved[i] === "string")
331
331
  descriptor.reservedName.push(this.reserved[i]);
332
332
  /* Ranges */ else
333
- descriptor.reservedRange.push(exports.DescriptorProto.ReservedRange.create({ start: this.reserved[i][0], end: this.reserved[i][1] }));
333
+ descriptor.reservedRange.push(exports.DescriptorProto.ReservedRange.create({ start: this.reserved[i][0], end: this.reserved[i][1] + 1 }));
334
334
 
335
335
  descriptor.options = toDescriptorOptions(this.options, exports.MessageOptions);
336
336
 
@@ -657,9 +657,10 @@ Enum.fromDescriptor = function fromDescriptor(descriptor, edition, nested) {
657
657
 
658
658
  // Construct values object
659
659
  var values = {},
660
- valuesOptions;
660
+ valuesOptions,
661
+ i;
661
662
  if (descriptor.value)
662
- for (var i = 0; i < descriptor.value.length; ++i) {
663
+ for (i = 0; i < descriptor.value.length; ++i) {
663
664
  var name = descriptor.value[i].name,
664
665
  valueName = name && name.length ? name : "NAME" + (descriptor.value[i].number || 0),
665
666
  value = descriptor.value[i].number || 0,
@@ -681,6 +682,16 @@ Enum.fromDescriptor = function fromDescriptor(descriptor, edition, nested) {
681
682
  if (!nested)
682
683
  enm._edition = edition;
683
684
 
685
+ /* Reserved... */ if (descriptor.reservedRange && descriptor.reservedRange.length || descriptor.reservedName && descriptor.reservedName.length) {
686
+ enm.reserved = [];
687
+ /* Ranges */ if (descriptor.reservedRange)
688
+ for (i = 0; i < descriptor.reservedRange.length; ++i)
689
+ enm.reserved.push([ descriptor.reservedRange[i].start, descriptor.reservedRange[i].end ]);
690
+ /* Names */ if (descriptor.reservedName)
691
+ for (i = 0; i < descriptor.reservedName.length; ++i)
692
+ enm.reserved.push(descriptor.reservedName[i]);
693
+ }
694
+
684
695
  return enm;
685
696
  };
686
697
 
@@ -691,19 +702,30 @@ Enum.fromDescriptor = function fromDescriptor(descriptor, edition, nested) {
691
702
  Enum.prototype.toDescriptor = function toDescriptor() {
692
703
 
693
704
  // Values
694
- var values = [];
695
- for (var i = 0, ks = Object.keys(this.values); i < ks.length; ++i)
705
+ var values = [],
706
+ i,
707
+ ks = Object.keys(this.values);
708
+ for (i = 0; i < ks.length; ++i)
696
709
  values.push(exports.EnumValueDescriptorProto.create({
697
710
  name: ks[i],
698
711
  number: this.values[ks[i]],
699
712
  options: this.valuesOptions && toDescriptorOptions(this.valuesOptions[ks[i]], exports.EnumValueOptions)
700
713
  }));
701
714
 
702
- return exports.EnumDescriptorProto.create({
715
+ var descriptor = exports.EnumDescriptorProto.create({
703
716
  name: this.name,
704
717
  value: values,
705
718
  options: toDescriptorOptions(this.options, exports.EnumOptions)
706
719
  });
720
+
721
+ /* Reserved... */ if (this.reserved)
722
+ for (i = 0; i < this.reserved.length; ++i)
723
+ /* Names */ if (typeof this.reserved[i] === "string")
724
+ descriptor.reservedName.push(this.reserved[i]);
725
+ /* Ranges */ else
726
+ descriptor.reservedRange.push(exports.EnumDescriptorProto.EnumReservedRange.create({ start: this.reserved[i][0], end: this.reserved[i][1] }));
727
+
728
+ return descriptor;
707
729
  };
708
730
 
709
731
  // --- OneOf ---
package/index.d.ts CHANGED
@@ -340,6 +340,9 @@ export class FieldBase extends ReflectionObject {
340
340
  */
341
341
  constructor(name: string, id: number, type: string, rule?: (string|{ [k: string]: any }), extend?: (string|{ [k: string]: any }), options?: { [k: string]: any }, comment?: string);
342
342
 
343
+ /** Field rule, if any. */
344
+ rule?: string;
345
+
343
346
  /** Field type. */
344
347
  type: string;
345
348
 
@@ -578,7 +581,7 @@ export class Message<T extends object = object> {
578
581
  * @param [properties] Properties to set
579
582
  * @returns Message instance
580
583
  */
581
- static create<T extends Message<T>>(this: Constructor<T>, properties?: { [k: string]: any }): Message<T>;
584
+ static create<T extends Message<T>>(this: Constructor<T>, properties?: { [k: string]: any }): T;
582
585
 
583
586
  /**
584
587
  * Encodes a message of this type.
@@ -1740,7 +1743,7 @@ export class Type extends NamespaceBase {
1740
1743
  * @param [properties] Properties to set
1741
1744
  * @returns Message instance
1742
1745
  */
1743
- create(properties?: { [k: string]: any }): Message<{}>;
1746
+ create(properties?: { [k: string]: any }): ReflectedMessage;
1744
1747
 
1745
1748
  /**
1746
1749
  * Sets up {@link Type#encode|encode}, {@link Type#decode|decode} and {@link Type#verify|verify}.
@@ -1772,7 +1775,7 @@ export class Type extends NamespaceBase {
1772
1775
  * @throws {Error} If the payload is not a reader or valid buffer
1773
1776
  * @throws {util.ProtocolError<{}>} If required fields are missing
1774
1777
  */
1775
- decode(reader: (Reader|Uint8Array), length?: number): Message<{}>;
1778
+ decode(reader: (Reader|Uint8Array), length?: number): ReflectedMessage;
1776
1779
 
1777
1780
  /**
1778
1781
  * Decodes a message of this type preceeded by its byte length as a varint.
@@ -1781,7 +1784,7 @@ export class Type extends NamespaceBase {
1781
1784
  * @throws {Error} If the payload is not a reader or valid buffer
1782
1785
  * @throws {util.ProtocolError} If required fields are missing
1783
1786
  */
1784
- decodeDelimited(reader: (Reader|Uint8Array)): Message<{}>;
1787
+ decodeDelimited(reader: (Reader|Uint8Array)): ReflectedMessage;
1785
1788
 
1786
1789
  /**
1787
1790
  * Verifies that field values are valid and that required fields are present.
@@ -1795,7 +1798,7 @@ export class Type extends NamespaceBase {
1795
1798
  * @param object Plain object to convert
1796
1799
  * @returns Message instance
1797
1800
  */
1798
- fromObject(object: { [k: string]: any }): Message<{}>;
1801
+ fromObject(object: { [k: string]: any }): ReflectedMessage;
1799
1802
 
1800
1803
  /**
1801
1804
  * Creates a plain object from a message of this type. Also converts values to other types if specified.
@@ -1984,6 +1987,9 @@ export type Constructor<T> = Function & { new(...params: any[]): T; prototype: T
1984
1987
  /** Properties type. */
1985
1988
  export type Properties<T> = { [P in keyof T]?: T[P] };
1986
1989
 
1990
+ /** Dynamically reflected message type. */
1991
+ export type ReflectedMessage = Message<{}> & { [k: string]: any };
1992
+
1987
1993
  /**
1988
1994
  * Callback as used by {@link util.asPromise}.
1989
1995
  * @param error Error, if any
@@ -2356,6 +2362,13 @@ export namespace util {
2356
2362
  length(): number;
2357
2363
  }
2358
2364
 
2365
+ /**
2366
+ * Tests if the specified key can affect object prototypes.
2367
+ * @param key Key to test
2368
+ * @returns `true` if the key is unsafe
2369
+ */
2370
+ function isUnsafeProperty(key: string): boolean;
2371
+
2359
2372
  /** Whether running within node or not. */
2360
2373
  let isNode: boolean;
2361
2374
 
@@ -2464,11 +2477,10 @@ export namespace util {
2464
2477
  /**
2465
2478
  * Merges the properties of the source object into the destination object.
2466
2479
  * @param dst Destination object
2467
- * @param src Source object
2468
- * @param [ifNotSet=false] Merges only if the key is not already set
2480
+ * @param src Source objects, optionally followed by an `ifNotSet` flag
2469
2481
  * @returns Destination object
2470
2482
  */
2471
- function merge(dst: { [k: string]: any }, src: { [k: string]: any }, ifNotSet?: boolean): { [k: string]: any };
2483
+ function merge(dst: { [k: string]: any }, ...src: any[]): { [k: string]: any };
2472
2484
 
2473
2485
  /** Schema declaration nesting limit. */
2474
2486
  let nestingLimit: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "protobufjs",
3
- "version": "8.4.0",
3
+ "version": "8.4.2",
4
4
  "versionScheme": "~",
5
5
  "description": "Protocol Buffers for JavaScript & TypeScript.",
6
6
  "author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
package/src/converter.js CHANGED
@@ -62,14 +62,14 @@ function genValuePartial_fromObject(gen, field, fieldIndex, prop) {
62
62
  ("m%s=d%s|0", prop, prop);
63
63
  break;
64
64
  case "uint64":
65
+ case "fixed64":
65
66
  isUnsigned = true;
66
67
  // eslint-disable-next-line no-fallthrough
67
68
  case "int64":
68
69
  case "sint64":
69
- case "fixed64":
70
70
  case "sfixed64": gen
71
71
  ("if(util.Long)")
72
- ("(m%s=util.Long.fromValue(d%s)).unsigned=%j", prop, prop, isUnsigned)
72
+ ("m%s=util.Long.fromValue(d%s,%j)", prop, prop, isUnsigned)
73
73
  ("else if(typeof d%s===\"string\")", prop)
74
74
  ("m%s=parseInt(d%s,10)", prop, prop)
75
75
  ("else if(typeof d%s===\"number\")", prop)
@@ -194,7 +194,7 @@ function genValuePartial_toObject(gen, field, fieldIndex, dstProp, srcProp) {
194
194
  if (field.resolvedType instanceof Enum) gen
195
195
  ("d%s=o.enums===String?(types[%i].values[m%s]===undefined?m%s:types[%i].values[m%s]):m%s", dstProp, fieldIndex, srcProp, srcProp, fieldIndex, srcProp, srcProp);
196
196
  else gen
197
- ("d%s=types[%i].toObject(m%s,o)", dstProp, fieldIndex, srcProp);
197
+ ("d%s=types[%i].toObject(m%s,o,q+1)", dstProp, fieldIndex, srcProp);
198
198
  } else {
199
199
  var isUnsigned = false;
200
200
  switch (field.type) {
@@ -203,11 +203,11 @@ function genValuePartial_toObject(gen, field, fieldIndex, dstProp, srcProp) {
203
203
  ("d%s=o.json&&!isFinite(m%s)?String(m%s):m%s", dstProp, srcProp, srcProp, srcProp);
204
204
  break;
205
205
  case "uint64":
206
+ case "fixed64":
206
207
  isUnsigned = true;
207
208
  // eslint-disable-next-line no-fallthrough
208
209
  case "int64":
209
210
  case "sint64":
210
- case "fixed64":
211
211
  case "sfixed64": gen
212
212
  ("if(typeof BigInt!==\"undefined\"&&o.longs===BigInt)")
213
213
  ("d%s=typeof m%s===\"number\"?BigInt(m%s):util.Long.fromBits(m%s.low>>>0,m%s.high>>>0,%j).toBigInt()", dstProp, srcProp, srcProp, srcProp, srcProp, isUnsigned)
@@ -238,9 +238,12 @@ converter.toObject = function toObject(mtype) {
238
238
  var fields = mtype.fieldsArray.slice().sort(util.compareFieldsById);
239
239
  if (!fields.length)
240
240
  return util.codegen()("return {}");
241
- var gen = util.codegen(["m", "o"], mtype.name + "$toObject")
241
+ var gen = util.codegen(["m", "o", "q"], mtype.name + "$toObject")
242
242
  ("if(!o)")
243
243
  ("o={}")
244
+ ("if(q===undefined)q=0")
245
+ ("if(q>util.recursionLimit)")
246
+ ("throw Error(\"max depth exceeded\")")
244
247
  ("var d={}");
245
248
 
246
249
  var repeatedFields = [],
@@ -326,7 +329,7 @@ converter.toObject = function toObject(mtype) {
326
329
  } else { gen
327
330
  ("if(m%s!=null&&m.hasOwnProperty(%j)){", prop, field.name); // !== undefined && !== null
328
331
  genValuePartial_toObject(gen, field, /* sorted */ index, prop);
329
- if (field.partOf) gen
332
+ if (field.partOf && !field.partOf.isProto3Optional) gen
330
333
  ("if(o.oneofs)")
331
334
  ("d%s=%j", util.safeProp(field.partOf.name), field.name);
332
335
  }
package/src/decoder.js CHANGED
@@ -63,7 +63,9 @@ function decoder(mtype) {
63
63
  else gen
64
64
  ("k=null");
65
65
 
66
- if (types.defaults[type] !== undefined) gen
66
+ if (types.long[type] !== undefined) gen
67
+ ("v=util.Long?util.Long.fromNumber(0,%j):0", type === "uint64" || type === "fixed64");
68
+ else if (types.defaults[type] !== undefined) gen
67
69
  ("v=%j", types.defaults[type]);
68
70
  else gen
69
71
  ("v=null");
package/src/encoder.js CHANGED
@@ -16,8 +16,8 @@ var Enum = require("./enum"),
16
16
  */
17
17
  function genTypePartial(gen, field, fieldIndex, ref) {
18
18
  return field.delimited
19
- ? gen("types[%i].encode(%s,w.uint32(%i)).uint32(%i)", fieldIndex, ref, (field.id << 3 | 3) >>> 0, (field.id << 3 | 4) >>> 0)
20
- : gen("types[%i].encode(%s,w.uint32(%i).fork()).ldelim()", fieldIndex, ref, (field.id << 3 | 2) >>> 0);
19
+ ? gen("types[%i].encode(%s,w.uint32(%i),q+1).uint32(%i)", fieldIndex, ref, (field.id << 3 | 3) >>> 0, (field.id << 3 | 4) >>> 0)
20
+ : gen("types[%i].encode(%s,w.uint32(%i).fork(),q+1).ldelim()", fieldIndex, ref, (field.id << 3 | 2) >>> 0);
21
21
  }
22
22
 
23
23
  /**
@@ -27,9 +27,12 @@ function genTypePartial(gen, field, fieldIndex, ref) {
27
27
  */
28
28
  function encoder(mtype) {
29
29
  /* eslint-disable no-unexpected-multiline, block-scoped-var, no-redeclare */
30
- var gen = util.codegen(["m", "w"], mtype.name + "$encode")
30
+ var gen = util.codegen(["m", "w", "q"], mtype.name + "$encode")
31
31
  ("if(!w)")
32
- ("w=Writer.create()");
32
+ ("w=Writer.create()")
33
+ ("if(q===undefined)q=0")
34
+ ("if(q>util.recursionLimit)")
35
+ ("throw Error(\"max depth exceeded\")");
33
36
 
34
37
  var i, ref;
35
38
 
@@ -55,7 +58,7 @@ function encoder(mtype) {
55
58
  else gen
56
59
  ("w.uint32(%i).fork().uint32(%i).%s(ks[i])", (field.id << 3 | 2) >>> 0, 8 | types.mapKey[field.keyType], field.keyType);
57
60
  if (wireType === undefined) gen
58
- ("types[%i].encode(%s[ks[i]],w.uint32(18).fork()).ldelim().ldelim()", index, ref); // can't be groups
61
+ ("types[%i].encode(%s[ks[i]],w.uint32(18).fork(),q+1).ldelim().ldelim()", index, ref); // can't be groups
59
62
  else gen
60
63
  (".uint32(%i).%s(%s[ks[i]]).ldelim()", 16 | wireType, type, ref);
61
64
  gen
package/src/enum.js CHANGED
@@ -86,8 +86,8 @@ Enum.prototype._resolveFeatures = function _resolveFeatures(edition) {
86
86
  ReflectionObject.prototype._resolveFeatures.call(this, edition);
87
87
 
88
88
  Object.keys(this.values).forEach(key => {
89
- var parentFeaturesCopy = Object.assign({}, this._features);
90
- this._valuesFeatures[key] = Object.assign(parentFeaturesCopy, this.valuesOptions && this.valuesOptions[key] && this.valuesOptions[key].features);
89
+ var parentFeaturesCopy = util.merge({}, this._features);
90
+ this._valuesFeatures[key] = util.merge(parentFeaturesCopy, this.valuesOptions && this.valuesOptions[key] && this.valuesOptions[key].features || {});
91
91
  });
92
92
 
93
93
  return this;
package/src/field.js CHANGED
@@ -11,7 +11,7 @@ var Enum = require("./enum"),
11
11
 
12
12
  var Type; // cyclic
13
13
 
14
- var ruleRe = /^required|optional|repeated$/;
14
+ var ruleRe = /^(?:required|optional|repeated)$/;
15
15
 
16
16
  /**
17
17
  * Constructs a new message field instance. Note that {@link MapField|map fields} have their own class.
@@ -86,9 +86,6 @@ function Field(name, id, type, rule, extend, options, comment) {
86
86
  * Field rule, if any.
87
87
  * @type {string|undefined}
88
88
  */
89
- if (rule === "proto3_optional") {
90
- rule = "optional";
91
- }
92
89
  this.rule = rule && rule !== "optional" ? rule : undefined; // toJSON
93
90
 
94
91
  /**
@@ -330,7 +327,7 @@ Field.prototype.resolve = function resolve() {
330
327
 
331
328
  // convert to internal data type if necesssary
332
329
  if (this.long) {
333
- this.typeDefault = util.Long.fromNumber(this.typeDefault, this.type.charAt(0) === "u");
330
+ this.typeDefault = util.Long.fromNumber(this.typeDefault, this.type === "uint64" || this.type === "fixed64");
334
331
 
335
332
  /* istanbul ignore else */
336
333
  if (Object.freeze)
@@ -100,5 +100,5 @@ protobuf.util = require("./util");
100
100
  // Set up possibly cyclic reflection dependencies
101
101
  protobuf.ReflectionObject._configure(protobuf.Root);
102
102
  protobuf.Namespace._configure(protobuf.Type, protobuf.Service, protobuf.Enum);
103
- protobuf.Root._configure(protobuf.Type);
103
+ protobuf.Root._configure(protobuf.Type, undefined, {});
104
104
  protobuf.Field._configure(protobuf.Type);
package/src/message.js CHANGED
@@ -36,7 +36,7 @@ function Message(properties) {
36
36
  /**
37
37
  * Creates a new message of this type using the specified properties.
38
38
  * @param {Object.<string,*>} [properties] Properties to set
39
- * @returns {Message<T>} Message instance
39
+ * @returns {T} Message instance
40
40
  * @template T extends Message<T>
41
41
  * @this Constructor<T>
42
42
  */
package/src/namespace.js CHANGED
@@ -68,7 +68,7 @@ Namespace.arrayToJSON = arrayToJSON;
68
68
  Namespace.isReservedId = function isReservedId(reserved, id) {
69
69
  if (reserved)
70
70
  for (var i = 0; i < reserved.length; ++i)
71
- if (typeof reserved[i] !== "string" && reserved[i][0] <= id && reserved[i][1] > id)
71
+ if (typeof reserved[i] !== "string" && reserved[i][0] <= id && reserved[i][1] >= id)
72
72
  return true;
73
73
  return false;
74
74
  };
package/src/object.js CHANGED
@@ -213,7 +213,7 @@ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition)
213
213
  throw new Error("Unknown edition for " + this.fullName);
214
214
  }
215
215
 
216
- var protoFeatures = Object.assign(this.options ? Object.assign({}, this.options.features) : {},
216
+ var protoFeatures = util.merge({}, this.options && this.options.features,
217
217
  this._inferLegacyProtoFeatures(edition));
218
218
 
219
219
  if (this._edition) {
@@ -230,19 +230,19 @@ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition)
230
230
  } else {
231
231
  throw new Error("Unknown edition: " + edition);
232
232
  }
233
- this._features = Object.assign(defaults, protoFeatures || {});
233
+ this._features = util.merge(defaults, protoFeatures);
234
234
  } else {
235
235
  // fields in Oneofs aren't actually children of them, so we have to
236
236
  // special-case it
237
237
  /* istanbul ignore else */
238
238
  if (this.partOf instanceof OneOf) {
239
- var lexicalParentFeaturesCopy = Object.assign({}, this.partOf._features);
240
- this._features = Object.assign(lexicalParentFeaturesCopy, protoFeatures || {});
239
+ var lexicalParentFeaturesCopy = util.merge({}, this.partOf._features);
240
+ this._features = util.merge(lexicalParentFeaturesCopy, protoFeatures);
241
241
  } else if (this.declaringField) {
242
242
  // Skip feature resolution of sister fields.
243
243
  } else if (this.parent) {
244
- var parentFeaturesCopy = Object.assign({}, this.parent._features);
245
- this._features = Object.assign(parentFeaturesCopy, protoFeatures || {});
244
+ var parentFeaturesCopy = util.merge({}, this.parent._features);
245
+ this._features = util.merge(parentFeaturesCopy, protoFeatures);
246
246
  } else {
247
247
  throw new Error("Unable to find a parent for " + this.fullName);
248
248
  }
package/src/parse.js CHANGED
@@ -27,6 +27,9 @@ var base10Re = /^[1-9][0-9]*$/,
27
27
  nameRe = /^[a-zA-Z_][a-zA-Z_0-9]*$/,
28
28
  typeRefRe = util.patterns.typeRefRe;
29
29
 
30
+ var maxFieldId = 536870911, // 2^29 - 1
31
+ maxEnumId = 2147483647; // 2^31 - 1
32
+
30
33
  /**
31
34
  * Result object returned from {@link parse}.
32
35
  * @interface IParserResult
@@ -146,7 +149,7 @@ function parse(source, root, options) {
146
149
  }
147
150
  }
148
151
 
149
- function readRanges(target, acceptStrings) {
152
+ function readRanges(target, acceptStrings, max, acceptNegative) {
150
153
  var token, start;
151
154
  do {
152
155
  if (acceptStrings && ((token = peek()) === "\"" || token === "'")) {
@@ -157,7 +160,7 @@ function parse(source, root, options) {
157
160
  }
158
161
  } else {
159
162
  try {
160
- target.push([ start = parseId(next()), skip("to", true) ? parseId(next()) : start ]);
163
+ target.push([ start = parseId(next(), acceptNegative, max), skip("to", true) ? parseId(next(), acceptNegative, max) : start ]);
161
164
  } catch (err) {
162
165
  if (acceptStrings && typeRefRe.test(token) && edition >= 2023) {
163
166
  target.push(token);
@@ -216,10 +219,10 @@ function parse(source, root, options) {
216
219
  throw illegal(token, "number", insideTryCatch);
217
220
  }
218
221
 
219
- function parseId(token, acceptNegative) {
222
+ function parseId(token, acceptNegative, max) {
220
223
  switch (token) {
221
224
  case "max": case "MAX": case "Max":
222
- return 536870911;
225
+ return max || maxFieldId;
223
226
  case "0":
224
227
  return 0;
225
228
  }
@@ -482,7 +485,7 @@ function parse(source, root, options) {
482
485
  name = applyCase(name);
483
486
  skip("=");
484
487
 
485
- var field = new Field(name, parseId(next()), type, rule, extend);
488
+ var field = new Field(name, parseId(next()), type, rule === "proto3_optional" ? "optional" : rule, extend);
486
489
 
487
490
  ifBlock(field, function parseField_block(token) {
488
491
 
@@ -677,7 +680,7 @@ function parse(source, root, options) {
677
680
  break;
678
681
 
679
682
  case "reserved":
680
- readRanges(enm.reserved || (enm.reserved = []), true);
683
+ readRanges(enm.reserved || (enm.reserved = []), true, maxEnumId, true);
681
684
  if(enm.reserved === undefined) enm.reserved = [];
682
685
  break;
683
686
 
package/src/root.js CHANGED
@@ -142,8 +142,12 @@ Root.prototype.load = function load(filename, options, callback) {
142
142
  }
143
143
 
144
144
  // Processes a single file
145
- function process(filename, source) {
145
+ function process(filename, source, depth) {
146
+ if (depth === undefined)
147
+ depth = 0;
146
148
  try {
149
+ if (depth > util.recursionLimit)
150
+ throw Error("max depth exceeded");
147
151
  if (util.isString(source) && source.charAt(0) === "{")
148
152
  source = JSON.parse(source);
149
153
  if (!util.isString(source))
@@ -156,11 +160,11 @@ Root.prototype.load = function load(filename, options, callback) {
156
160
  if (parsed.imports)
157
161
  for (; i < parsed.imports.length; ++i)
158
162
  if (resolved = getBundledFileName(parsed.imports[i]) || self.resolvePath(filename, parsed.imports[i]))
159
- fetch(resolved);
163
+ fetch(resolved, false, depth + 1);
160
164
  if (parsed.weakImports)
161
165
  for (i = 0; i < parsed.weakImports.length; ++i)
162
166
  if (resolved = getBundledFileName(parsed.weakImports[i]) || self.resolvePath(filename, parsed.weakImports[i]))
163
- fetch(resolved, true);
167
+ fetch(resolved, true, depth + 1);
164
168
  }
165
169
  } catch (err) {
166
170
  finish(err);
@@ -171,7 +175,9 @@ Root.prototype.load = function load(filename, options, callback) {
171
175
  }
172
176
 
173
177
  // Fetches a single file
174
- function fetch(filename, weak) {
178
+ function fetch(filename, weak, depth) {
179
+ if (depth === undefined)
180
+ depth = 0;
175
181
  filename = getBundledFileName(filename) || filename;
176
182
 
177
183
  // Skip if already loaded / attempted
@@ -183,12 +189,12 @@ Root.prototype.load = function load(filename, options, callback) {
183
189
  // Shortcut bundled definitions
184
190
  if (Object.prototype.hasOwnProperty.call(common, filename)) {
185
191
  if (sync) {
186
- process(filename, common[filename]);
192
+ process(filename, common[filename], depth);
187
193
  } else {
188
194
  ++queued;
189
195
  setTimeout(function() {
190
196
  --queued;
191
- process(filename, common[filename]);
197
+ process(filename, common[filename], depth);
192
198
  });
193
199
  }
194
200
  return;
@@ -204,7 +210,7 @@ Root.prototype.load = function load(filename, options, callback) {
204
210
  finish(err);
205
211
  return;
206
212
  }
207
- process(filename, source);
213
+ process(filename, source, depth);
208
214
  } else {
209
215
  ++queued;
210
216
  self.fetch(filename, function(err, source) {
@@ -221,7 +227,7 @@ Root.prototype.load = function load(filename, options, callback) {
221
227
  finish(null, self);
222
228
  return;
223
229
  }
224
- process(filename, source);
230
+ process(filename, source, depth);
225
231
  });
226
232
  }
227
233
  }
package/src/type.js CHANGED
@@ -458,7 +458,7 @@ Type.prototype.isReservedName = function isReservedName(name) {
458
458
  /**
459
459
  * Creates a new message of this type using the specified properties.
460
460
  * @param {Object.<string,*>} [properties] Properties to set
461
- * @returns {Message<{}>} Message instance
461
+ * @returns {ReflectedMessage} Message instance
462
462
  */
463
463
  Type.prototype.create = function create(properties) {
464
464
  return new this.ctor(properties);
@@ -524,8 +524,8 @@ Type.prototype.setup = function setup() {
524
524
  * @param {Writer} [writer] Writer to encode to
525
525
  * @returns {Writer} writer
526
526
  */
527
- Type.prototype.encode = function encode_setup(message, writer) {
528
- return this.setup().encode(message, writer); // overrides this method
527
+ Type.prototype.encode = function encode_setup(message, writer) { // eslint-disable-line no-unused-vars
528
+ return this.setup().encode.apply(this, arguments); // overrides this method
529
529
  };
530
530
 
531
531
  /**
@@ -542,7 +542,7 @@ Type.prototype.encodeDelimited = function encodeDelimited(message, writer) {
542
542
  * Decodes a message of this type.
543
543
  * @param {Reader|Uint8Array} reader Reader or buffer to decode from
544
544
  * @param {number} [length] Length of the message, if known beforehand
545
- * @returns {Message<{}>} Decoded message
545
+ * @returns {ReflectedMessage} Decoded message
546
546
  * @throws {Error} If the payload is not a reader or valid buffer
547
547
  * @throws {util.ProtocolError<{}>} If required fields are missing
548
548
  */
@@ -553,7 +553,7 @@ Type.prototype.decode = function decode_setup(reader, length) { // eslint-disabl
553
553
  /**
554
554
  * Decodes a message of this type preceeded by its byte length as a varint.
555
555
  * @param {Reader|Uint8Array} reader Reader or buffer to decode from
556
- * @returns {Message<{}>} Decoded message
556
+ * @returns {ReflectedMessage} Decoded message
557
557
  * @throws {Error} If the payload is not a reader or valid buffer
558
558
  * @throws {util.ProtocolError} If required fields are missing
559
559
  */
@@ -575,7 +575,7 @@ Type.prototype.verify = function verify_setup(message) { // eslint-disable-line
575
575
  /**
576
576
  * Creates a new message of this type from a plain object. Also converts values to their respective internal types.
577
577
  * @param {Object.<string,*>} object Plain object to convert
578
- * @returns {Message<{}>} Message instance
578
+ * @returns {ReflectedMessage} Message instance
579
579
  */
580
580
  Type.prototype.fromObject = function fromObject(object) { // eslint-disable-line no-unused-vars
581
581
  return this.setup().fromObject.apply(this, arguments);
@@ -606,8 +606,8 @@ Type.prototype.fromObject = function fromObject(object) { // eslint-disable-line
606
606
  * @param {IConversionOptions} [options] Conversion options
607
607
  * @returns {Object.<string,*>} Plain object
608
608
  */
609
- Type.prototype.toObject = function toObject(message, options) {
610
- return this.setup().toObject(message, options);
609
+ Type.prototype.toObject = function toObject(message, options) { // eslint-disable-line no-unused-vars
610
+ return this.setup().toObject.apply(this, arguments);
611
611
  };
612
612
 
613
613
  /**
package/src/typescript.js CHANGED
@@ -17,3 +17,9 @@ var Constructor;
17
17
  * @typedef {{ [P in keyof T]?: T[P] }} Properties
18
18
  */
19
19
  var Properties;
20
+
21
+ /**
22
+ * Dynamically reflected message type.
23
+ * @typedef {Message<{}> & { [k: string]: any }} ReflectedMessage
24
+ */
25
+ var ReflectedMessage;
@@ -14,7 +14,7 @@ function EventEmitter() {
14
14
  * @type {Object.<string,*>}
15
15
  * @private
16
16
  */
17
- this._listeners = {};
17
+ this._listeners = Object.create(null);
18
18
  }
19
19
 
20
20
  /**
@@ -48,12 +48,14 @@ EventEmitter.prototype.on = function on(evt, fn, ctx) {
48
48
  */
49
49
  EventEmitter.prototype.off = function off(evt, fn) {
50
50
  if (evt === undefined)
51
- this._listeners = {};
51
+ this._listeners = Object.create(null);
52
52
  else {
53
53
  if (fn === undefined)
54
54
  this._listeners[evt] = [];
55
55
  else {
56
56
  var listeners = this._listeners[evt];
57
+ if (!listeners)
58
+ return this;
57
59
  for (var i = 0; i < listeners.length;)
58
60
  if (listeners[i].fn === fn)
59
61
  listeners.splice(i, 1);