protobufjs 8.7.2 → 8.8.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/README.md CHANGED
@@ -316,26 +316,32 @@ protobuf.js is validated against the official Protocol Buffers conformance suite
316
316
  | ↳ Proto2 | 100.00% (707/707) | 100.00% (489/489) | 100.00% (218/218) |
317
317
  | ↳ Proto3 | 100.00% (707/707) | 100.00% (486/486) | 100.00% (221/221) |
318
318
  | ↳ Editions | 100.00% (1421/1421) | 100.00% (983/983) | 100.00% (438/438) |
319
- | ProtoJSON | 100.00% (2796/2796) | 100.00% (2362/2362) | 100.00% (434/434) |
319
+ | ProtoJSON | 100.00% (2814/2814) | 100.00% (2362/2362) | 100.00% (452/452) |
320
320
  | TextFormat | 100.00% (909/909) | 100.00% (845/845) | 100.00% (64/64) |
321
- | Overall | 100.00% (6540/6540) | 100.00% (5165/5165) | 100.00% (1375/1375) |
321
+ | Overall | 100.00% (6558/6558) | 100.00% (5165/5165) | 100.00% (1393/1393) |
322
322
 
323
323
  <!-- END CONFORMANCE DATA -->
324
324
 
325
+ | Edition | Supported since
326
+ |---------|----------------
327
+ | 2023 | v7.5.0
328
+ | 2024 | v8.0.0
329
+ | 2026 | v8.8.0
330
+
325
331
  [Structured results](https://github.com/protobufjs/protobuf.js/actions/workflows/test.yml?query=branch%3Amaster+event%3Apush) of the conformance tests are also available as CI artifacts.
326
332
 
327
333
  ## Performance
328
334
 
329
- Both reflection and static modes use specialized encoders and decoders backed by the same hand-tuned reader and writer primitives.
335
+ protobuf.js's reflection and static modes share the same code-generation backend and underlying hand-tuned reader and writer primitives. Reflection mode emits specialized encoders and decoders just in time, while static mode emits equivalent code ahead of time.
330
336
 
331
- The repository includes a [benchmark suite](./bench) you can run yourself. It compares protobuf.js with other general-purpose JavaScript implementations across three substantially different cases: our classic common message shape and two unmodified, structurally distinct fixtures sourced externally. The suite measures each library's recommended serialization and deserialization path using identical schemas and inputs, with JSON included as an additional baseline. Across these cases, protobuf.js is a clear upgrade over using JSON and consistently the fastest Protobuf implementation by a considerable margin.
337
+ To see how this architecture compares in practice, the repository includes a reproducible [benchmark suite](./bench) measuring both modes alongside other general-purpose JavaScript implementations across three cases: our classic common message shape and two unmodified, structurally distinct fixtures sourced from other implementations. Each library is tested through its recommended serialization and deserialization path using identical schemas and message contents.
332
338
 
333
339
  <!-- BEGIN BENCHMARK DATA -->
334
340
 
335
341
  <picture>
336
342
  <source media="(prefers-color-scheme: dark)" srcset="./bench/results/encode-dark.svg">
337
343
  <source media="(prefers-color-scheme: light)" srcset="./bench/results/encode-light.svg">
338
- <img alt="Encode benchmark" src="./bench/results/encode.svg">
344
+ <img alt="Encode Throughput" src="./bench/results/encode.svg">
339
345
  </picture>
340
346
 
341
347
  <details>
@@ -343,18 +349,18 @@ The repository includes a [benchmark suite](./bench) you can run yourself. It co
343
349
 
344
350
  | Implementation | Common | Vector tile | Buf perf |
345
351
  | --- | ---: | ---: | ---: |
346
- | protobuf.js static | **5.34M ops/s** &nbsp; <small>1.0x</small> | **3.09K ops/s** &nbsp; <small>1.0x</small> | 43.1K ops/s &nbsp; <small>1.0x</small> |
347
- | protobuf.js reflect | 4.89M ops/s &nbsp; <small>1.1x</small> | 3.03K ops/s &nbsp; <small>1.0x</small> | **43.3K ops/s** &nbsp; <small>1.0x</small> |
348
- | JSON | 2.09M ops/s &nbsp; <small>2.6x</small> | 897 ops/s &nbsp; <small>3.4x</small> | 6.70K ops/s &nbsp; <small>6.5x</small> |
349
- | protoc-gen-js | 1.03M ops/s &nbsp; <small>5.2x</small> | 700 ops/s &nbsp; <small>4.4x</small> | 13.9K ops/s &nbsp; <small>3.1x</small> |
350
- | protoc-gen-es | 402K ops/s &nbsp; <small>13.3x</small> | 235 ops/s &nbsp; <small>13.2x</small> | 8.22K ops/s &nbsp; <small>5.3x</small> |
352
+ | protobuf.js static | **5.28M ops/s** &nbsp; <small>1.0x</small> | 3.06K ops/s &nbsp; <small>1.0x</small> | **49.2K ops/s** &nbsp; <small>1.0x</small> |
353
+ | protobuf.js reflect | 5.16M ops/s &nbsp; <small>1.0x</small> | **3.08K ops/s** &nbsp; <small>1.0x</small> | 47.5K ops/s &nbsp; <small>1.0x</small> |
354
+ | JSON | 3.44M ops/s &nbsp; <small>1.5x</small> | 1.50K ops/s &nbsp; <small>2.1x</small> | 7.13K ops/s &nbsp; <small>6.9x</small> |
355
+ | protoc-gen-js | 1.05M ops/s &nbsp; <small>5.0x</small> | 691 ops/s &nbsp; <small>4.5x</small> | 15.0K ops/s &nbsp; <small>3.3x</small> |
356
+ | protoc-gen-es | 1.22M ops/s &nbsp; <small>4.3x</small> | 1.14K ops/s &nbsp; <small>2.7x</small> | 35.8K ops/s &nbsp; <small>1.4x</small> |
351
357
 
352
358
  </details>
353
359
 
354
360
  <picture>
355
361
  <source media="(prefers-color-scheme: dark)" srcset="./bench/results/decode-dark.svg">
356
362
  <source media="(prefers-color-scheme: light)" srcset="./bench/results/decode-light.svg">
357
- <img alt="Decode benchmark" src="./bench/results/decode.svg">
363
+ <img alt="Decode Throughput" src="./bench/results/decode.svg">
358
364
  </picture>
359
365
 
360
366
  <details>
@@ -362,22 +368,23 @@ The repository includes a [benchmark suite](./bench) you can run yourself. It co
362
368
 
363
369
  | Implementation | Common | Vector tile | Buf perf |
364
370
  | --- | ---: | ---: | ---: |
365
- | protobuf.js static | 6.45M ops/s &nbsp; <small>1.1x</small> | 2.70K ops/s &nbsp; <small>1.1x</small> | **81.7K ops/s** &nbsp; <small>1.0x</small> |
366
- | protobuf.js reflect | **6.93M ops/s** &nbsp; <small>1.0x</small> | **2.99K ops/s** &nbsp; <small>1.0x</small> | 80.3K ops/s &nbsp; <small>1.0x</small> |
367
- | JSON | 1.37M ops/s &nbsp; <small>5.0x</small> | 1.06K ops/s &nbsp; <small>2.8x</small> | 19.5K ops/s &nbsp; <small>4.2x</small> |
368
- | protoc-gen-js | 811K ops/s &nbsp; <small>8.5x</small> | 851 ops/s &nbsp; <small>3.5x</small> | 21.7K ops/s &nbsp; <small>3.8x</small> |
369
- | protoc-gen-es | 691K ops/s &nbsp; <small>10.0x</small> | 376 ops/s &nbsp; <small>8.0x</small> | 14.3K ops/s &nbsp; <small>5.7x</small> |
371
+ | protobuf.js static | 5.84M ops/s &nbsp; <small>1.1x</small> | 2.45K ops/s &nbsp; <small>1.1x</small> | **78.9K ops/s** &nbsp; <small>1.0x</small> |
372
+ | protobuf.js reflect | **6.54M ops/s** &nbsp; <small>1.0x</small> | **2.66K ops/s** &nbsp; <small>1.0x</small> | 77.0K ops/s &nbsp; <small>1.0x</small> |
373
+ | JSON | 1.58M ops/s &nbsp; <small>4.1x</small> | 1.21K ops/s &nbsp; <small>2.2x</small> | 21.0K ops/s &nbsp; <small>3.8x</small> |
374
+ | protoc-gen-js | 701K ops/s &nbsp; <small>9.3x</small> | 946 ops/s &nbsp; <small>2.8x</small> | 21.5K ops/s &nbsp; <small>3.7x</small> |
375
+ | protoc-gen-es | 1.67M ops/s &nbsp; <small>3.9x</small> | 1.19K ops/s &nbsp; <small>2.2x</small> | 31.0K ops/s &nbsp; <small>2.5x</small> |
370
376
 
371
377
  </details>
372
378
 
373
379
  <!-- END BENCHMARK DATA -->
374
380
 
375
- [Structured results](./bench/results/latest.json) and environment details for this run are also available as committed artifacts.
381
+ [Structured results](./bench/results/latest.json) include environment details for this run and are committed alongside the charts. The suite also runs in CI.
376
382
 
377
383
  To run the benchmark on your own hardware:
378
384
 
379
385
  ```sh
380
386
  npm --prefix bench install
387
+ npm --prefix bench run generate
381
388
  npm run bench
382
389
  ```
383
390
 
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * protobuf.js v8.7.2 (c) 2016, daniel wirtz
3
- * compiled sat, 08 aug 2026 13:15:56 utc
2
+ * protobuf.js v8.8.1 (c) 2016, daniel wirtz
3
+ * compiled sun, 11 oct 2026 17:08:01 utc
4
4
  * licensed under the bsd-3-clause license
5
5
  * see: https://github.com/dcodeio/protobuf.js for details
6
6
  */
@@ -446,7 +446,17 @@ function decoder(mtype) {
446
446
  ("if(q===undefined)q=0")
447
447
  ("if(q>Reader.recursionLimit)")
448
448
  ("throw Error(\"max depth exceeded\")")
449
- ("var c=l===undefined?r.len:r.pos+l,m=g||new C" + (hasMapField ? ",k,v" : needsValueVar ? ",v" : ""))
449
+ ("var c,m" + (hasMapField ? ",k,v" : needsValueVar ? ",v" : ""))
450
+ ("if(l===undefined)")
451
+ ("c=r.len")
452
+ ("else{")
453
+ ("c=r.pos+l")
454
+ ("if(c>r.len)")
455
+ ("throw RangeError(\"index out of range\")")
456
+ ("l=r.len")
457
+ ("r.len=c")
458
+ ("}")
459
+ ("m=g||new C")
450
460
  ("while(r.pos<c){")
451
461
  ("var s=r.pos")
452
462
  ("var t=r.tag()")
@@ -473,7 +483,10 @@ function decoder(mtype) {
473
483
  ("if(%s===util.emptyObject)", ref)
474
484
  ("%s={}", ref);
475
485
  gen
476
- ("var c2=r.uint32()+r.pos");
486
+ ("var c2=r.size()+r.pos")
487
+ ("if(c2>r.len)")
488
+ ("throw RangeError(\"index out of range\")")
489
+ ("r.len=c2");
477
490
 
478
491
  if (types.defaults[field.keyType] !== undefined) gen
479
492
  ("k=%j", types.defaults[field.keyType]);
@@ -502,7 +515,7 @@ function decoder(mtype) {
502
515
  ("break");
503
516
 
504
517
  if (types.basic[type] === undefined) gen
505
- ("v=types[%i].decode(r,r.uint32(),undefined,q+1,v)", i); // can't be groups
518
+ ("v=types[%i].decode(r,r.size(),undefined,q+1,v)", i); // can't be groups
506
519
  else gen
507
520
  ("v=r.%s()", type === "string" ? stringMethod(field) : type);
508
521
 
@@ -511,6 +524,10 @@ function decoder(mtype) {
511
524
  ("}")
512
525
  ("r.skipType(u,q,t2)")
513
526
  ("}");
527
+ gen
528
+ ("if(r.pos!==c2)")
529
+ ("throw RangeError(\"index out of range\")")
530
+ ("r.len=c");
514
531
 
515
532
  if (closed) { gen
516
533
  ("if(types[%i].valuesById[v]===undefined){", i);
@@ -543,7 +560,10 @@ function decoder(mtype) {
543
560
  ("if(u===2){");
544
561
  if (closed) {
545
562
  gen
546
- ("var c2=r.uint32()+r.pos")
563
+ ("var c2=r.size()+r.pos")
564
+ ("if(c2>r.len)")
565
+ ("throw RangeError(\"index out of range\")")
566
+ ("r.len=c2")
547
567
  ("while(r.pos<c2){")
548
568
  ("s=r.pos")
549
569
  ("v=r.%s()", type)
@@ -554,6 +574,10 @@ function decoder(mtype) {
554
574
  ("}else");
555
575
  genPreserveUnknown(gen, "util.rawField(" + field.id + ",0,r.raw(s,r.pos))")
556
576
  ("}");
577
+ gen
578
+ ("if(r.pos!==c2)")
579
+ ("throw RangeError(\"index out of range\")")
580
+ ("r.len=c");
557
581
  } else gen
558
582
  ("if(!(%s&&%s.length))", ref, ref)
559
583
  ("%s=[]", ref)
@@ -574,7 +598,7 @@ function decoder(mtype) {
574
598
  if (field.delimited) gen
575
599
  ("%s.push(types[%i].decode(r,undefined,%i,q+1))", ref, i, field.id * 8 + 4);
576
600
  else gen
577
- ("%s.push(types[%i].decode(r,r.uint32(),undefined,q+1))", ref, i);
601
+ ("%s.push(types[%i].decode(r,r.size(),undefined,q+1))", ref, i);
578
602
  } else if (closed) { gen
579
603
  ("v=r.%s()", type)
580
604
  ("if(types[%i].valuesById[v]!==undefined){", i)
@@ -595,7 +619,7 @@ function decoder(mtype) {
595
619
  if (field.delimited) gen
596
620
  ("%s=types[%i].decode(r,undefined,%i,q+1,%s)", ref, i, field.id * 8 + 4, ref);
597
621
  else gen
598
- ("%s=types[%i].decode(r,r.uint32(),undefined,q+1,%s)", ref, i, ref);
622
+ ("%s=types[%i].decode(r,r.size(),undefined,q+1,%s)", ref, i, ref);
599
623
  }
600
624
  else if (field.hasPresence) {
601
625
  gen
@@ -662,6 +686,11 @@ function decoder(mtype) {
662
686
  ("r.skipType(%s,q,t)", i ? "u" : "t&7");
663
687
  genPreserveUnknown(gen, "r.raw(s,r.pos)")
664
688
  ("}")
689
+ ("if(l!==undefined){")
690
+ ("if(r.pos!==c)")
691
+ ("throw RangeError(\"index out of range\")")
692
+ ("r.len=l")
693
+ ("}")
665
694
  ("if(z!==undefined)")
666
695
  ("throw Error(\"missing end group\")");
667
696
 
@@ -882,6 +911,12 @@ function Enum(name, values, options, comment, comments, valuesOptions) {
882
911
  */
883
912
  this.reserved = undefined; // toJSON
884
913
 
914
+ /**
915
+ * Declared symbol visibility, if any.
916
+ * @type {"local"|"export"|undefined}
917
+ */
918
+ this.visibility = undefined; // toJSON
919
+
885
920
  // Note that values inherit valuesById on their prototype which makes them a TypeScript-
886
921
  // compatible enum. This is used by pbts to write actual enum definitions that work for
887
922
  // static and reflection code alike instead of emitting generic object definitions.
@@ -918,6 +953,7 @@ Enum.prototype._resolveFeatures = function _resolveFeatures(edition) {
918
953
  * @property {Object.<string,*>} [options] Enum options
919
954
  * @property {Object.<string,Object.<string,*>>} [valuesOptions] Enum value options
920
955
  * @property {Array.<number[]|string>} [reserved] Reserved ranges
956
+ * @property {"local"|"export"} [visibility] Declared symbol visibility
921
957
  * @property {string|null} [comment] Enum comment
922
958
  * @property {Object.<string,string|null>} [comments] Value comments
923
959
  */
@@ -932,6 +968,8 @@ Enum.prototype._resolveFeatures = function _resolveFeatures(edition) {
932
968
  Enum.fromJSON = function fromJSON(name, json) {
933
969
  var enm = new Enum(name, json.values, json.options, json.comment, json.comments, json.valuesOptions);
934
970
  enm.reserved = json.reserved;
971
+ if (json.visibility)
972
+ enm.visibility = json.visibility;
935
973
  if (json.edition)
936
974
  enm._edition = json.edition;
937
975
  enm._defaultEdition = "proto3"; // For backwards-compatibility.
@@ -951,6 +989,7 @@ Enum.prototype.toJSON = function toJSON(toJSONOptions) {
951
989
  "valuesOptions" , this.valuesOptions,
952
990
  "values" , this.values,
953
991
  "reserved" , this.reserved && this.reserved.length ? this.reserved : undefined,
992
+ "visibility" , this.visibility,
954
993
  "comment" , keepComments ? this.comment : undefined,
955
994
  "comments" , keepComments ? this.comments : undefined
956
995
  ]);
@@ -2761,10 +2800,11 @@ var Root; // cyclic
2761
2800
 
2762
2801
  /* eslint-disable no-warning-comments */
2763
2802
  // TODO: Replace with embedded proto.
2764
- var editions2024Defaults = {enum_type: "OPEN", field_presence: "EXPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY", enforce_naming_style: "STYLE2024", default_symbol_visibility: "EXPORT_TOP_LEVEL" };
2765
- var editions2023Defaults = {enum_type: "OPEN", field_presence: "EXPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY", enforce_naming_style: "STYLE_LEGACY", default_symbol_visibility: "EXPORT_ALL" };
2766
2803
  var proto2Defaults = {enum_type: "CLOSED", field_presence: "EXPLICIT", json_format: "LEGACY_BEST_EFFORT", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "EXPANDED", utf8_validation: "NONE", enforce_naming_style: "STYLE_LEGACY", default_symbol_visibility: "EXPORT_ALL" };
2767
2804
  var proto3Defaults = {enum_type: "OPEN", field_presence: "IMPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY", enforce_naming_style: "STYLE_LEGACY", default_symbol_visibility: "EXPORT_ALL" };
2805
+ var editions2023Defaults = {enum_type: "OPEN", field_presence: "EXPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY", enforce_naming_style: "STYLE_LEGACY", default_symbol_visibility: "EXPORT_ALL" };
2806
+ var editions2024Defaults = {enum_type: "OPEN", field_presence: "EXPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY", enforce_naming_style: "STYLE2024", default_symbol_visibility: "EXPORT_TOP_LEVEL" };
2807
+ var editions2026Defaults = {enum_type: "OPEN", field_presence: "EXPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY", enforce_naming_style: "STYLE2026", default_symbol_visibility: "STRICT", enforce_proto_limits: "PROTO_LIMITS2026" };
2768
2808
 
2769
2809
  /**
2770
2810
  * Constructs a new reflection object instance.
@@ -2978,6 +3018,8 @@ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition)
2978
3018
  defaults = Object.assign({}, editions2023Defaults);
2979
3019
  } else if (edition === "2024") {
2980
3020
  defaults = Object.assign({}, editions2024Defaults);
3021
+ } else if (edition === "2026") {
3022
+ defaults = Object.assign({}, editions2026Defaults);
2981
3023
  } else {
2982
3024
  throw new Error("Unknown edition: " + edition);
2983
3025
  }
@@ -3474,12 +3516,32 @@ Reader.prototype.raw = function read_raw(start, end) {
3474
3516
  return this.buf.subarray(start, end);
3475
3517
  };
3476
3518
 
3519
+ function readVarint32NearEnd(reader) {
3520
+ // Safely read up to four bytes of a varint32 near the reader limit
3521
+ var value = 0;
3522
+ for (var i = 0; i < 4; ++i) {
3523
+ if (reader.pos >= reader.len)
3524
+ throw indexOutOfRange(reader);
3525
+ var b = reader.buf[reader.pos++];
3526
+ value = (value | (b & 127) << i * 7) >>> 0;
3527
+ if (b < 128)
3528
+ return value;
3529
+ }
3530
+ throw indexOutOfRange(reader);
3531
+ }
3532
+
3477
3533
  /**
3478
3534
  * Reads a varint as an unsigned 32 bit value.
3479
3535
  * @function
3480
3536
  * @returns {number} Value read
3481
3537
  */
3482
3538
  Reader.prototype.uint32 = function read_uint32() {
3539
+ if (this.len - this.pos < 5) {
3540
+ if (this.pos >= this.len)
3541
+ throw indexOutOfRange(this);
3542
+ if (this.buf[this.pos] >= 128)
3543
+ return readVarint32NearEnd(this);
3544
+ }
3483
3545
  var buf = this.buf,
3484
3546
  pos = this.pos,
3485
3547
  value = (buf[pos] & 127) >>> 0;
@@ -3530,6 +3592,12 @@ Reader.prototype.uint32 = function read_uint32() {
3530
3592
  * @returns {number} Tag read
3531
3593
  */
3532
3594
  Reader.prototype.tag = function read_tag() {
3595
+ if (this.len - this.pos < 5) {
3596
+ if (this.pos >= this.len)
3597
+ throw indexOutOfRange(this);
3598
+ if (this.buf[this.pos] >= 128)
3599
+ return readVarint32NearEnd(this);
3600
+ }
3533
3601
  var buf = this.buf,
3534
3602
  pos = this.pos,
3535
3603
  value = (buf[pos] & 127) >>> 0;
@@ -3562,6 +3630,45 @@ Reader.prototype.tag = function read_tag() {
3562
3630
  throw Error("invalid tag encoding");
3563
3631
  };
3564
3632
 
3633
+ /**
3634
+ * Reads a varint length prefix within signed 32 bit range.
3635
+ * @returns {number} Length read
3636
+ */
3637
+ Reader.prototype.size = function read_size() {
3638
+ if (this.len - this.pos < 5) {
3639
+ if (this.pos >= this.len)
3640
+ throw indexOutOfRange(this);
3641
+ if (this.buf[this.pos] >= 128)
3642
+ return readVarint32NearEnd(this);
3643
+ }
3644
+ var buf = this.buf,
3645
+ pos = this.pos,
3646
+ value = (buf[pos] & 127) >>> 0;
3647
+ if (buf[pos++] < 128) {
3648
+ this.pos = pos;
3649
+ return value;
3650
+ }
3651
+ value = (value | (buf[pos] & 127) << 7) >>> 0;
3652
+ if (buf[pos++] < 128) {
3653
+ this.pos = pos;
3654
+ return value;
3655
+ }
3656
+ value = (value | (buf[pos] & 127) << 14) >>> 0;
3657
+ if (buf[pos++] < 128) {
3658
+ this.pos = pos;
3659
+ return value;
3660
+ }
3661
+ value = (value | (buf[pos] & 127) << 21) >>> 0;
3662
+ if (buf[pos++] < 128) {
3663
+ this.pos = pos;
3664
+ return value;
3665
+ }
3666
+ this.pos = pos + 1;
3667
+ if (buf[pos] > 7)
3668
+ throw Error("invalid length encoding");
3669
+ return (value | buf[pos] << 28) >>> 0;
3670
+ };
3671
+
3565
3672
  /**
3566
3673
  * Reads a varint as a signed 32 bit value.
3567
3674
  * @returns {number} Value read
@@ -3775,7 +3882,9 @@ Reader.prototype.double = function read_double() {
3775
3882
  */
3776
3883
  Reader.prototype.uint32s = function read_uint32s(array) {
3777
3884
  if (array === undefined) array = [];
3778
- var end = this.uint32() + this.pos, buf = this.buf, pos = this.pos, value;
3885
+ var end = this.size() + this.pos, len = this.len, buf = this.buf, pos = this.pos, value;
3886
+ if (end > len) throw indexOutOfRange(this, end - this.pos);
3887
+ this.len = end;
3779
3888
  while (pos < end) {
3780
3889
  value = buf[pos++];
3781
3890
  if (value < 128)
@@ -3787,6 +3896,8 @@ Reader.prototype.uint32s = function read_uint32s(array) {
3787
3896
  }
3788
3897
  }
3789
3898
  this.pos = pos;
3899
+ if (pos !== end) throw RangeError("index out of range");
3900
+ this.len = len;
3790
3901
  return array;
3791
3902
  };
3792
3903
 
@@ -3797,7 +3908,9 @@ Reader.prototype.uint32s = function read_uint32s(array) {
3797
3908
  */
3798
3909
  Reader.prototype.int32s = function read_int32s(array) {
3799
3910
  if (array === undefined) array = [];
3800
- var end = this.uint32() + this.pos, buf = this.buf, pos = this.pos, value;
3911
+ var end = this.size() + this.pos, len = this.len, buf = this.buf, pos = this.pos, value;
3912
+ if (end > len) throw indexOutOfRange(this, end - this.pos);
3913
+ this.len = end;
3801
3914
  while (pos < end) {
3802
3915
  value = buf[pos++];
3803
3916
  if (value < 128)
@@ -3809,6 +3922,8 @@ Reader.prototype.int32s = function read_int32s(array) {
3809
3922
  }
3810
3923
  }
3811
3924
  this.pos = pos;
3925
+ if (pos !== end) throw RangeError("index out of range");
3926
+ this.len = len;
3812
3927
  return array;
3813
3928
  };
3814
3929
 
@@ -3819,9 +3934,13 @@ Reader.prototype.int32s = function read_int32s(array) {
3819
3934
  */
3820
3935
  Reader.prototype.sint32s = function read_sint32s(array) {
3821
3936
  if (array === undefined) array = [];
3822
- var end = this.uint32() + this.pos;
3937
+ var end = this.size() + this.pos, len = this.len;
3938
+ if (end > len) throw indexOutOfRange(this, end - this.pos);
3939
+ this.len = end;
3823
3940
  while (this.pos < end)
3824
3941
  array.push(this.sint32());
3942
+ if (this.pos !== end) throw RangeError("index out of range");
3943
+ this.len = len;
3825
3944
  return array;
3826
3945
  };
3827
3946
 
@@ -3832,7 +3951,9 @@ Reader.prototype.sint32s = function read_sint32s(array) {
3832
3951
  */
3833
3952
  Reader.prototype.bools = function read_bools(array) {
3834
3953
  if (array === undefined) array = [];
3835
- var end = this.uint32() + this.pos, buf = this.buf, pos = this.pos, value;
3954
+ var end = this.size() + this.pos, len = this.len, buf = this.buf, pos = this.pos, value;
3955
+ if (end > len) throw indexOutOfRange(this, end - this.pos);
3956
+ this.len = end;
3836
3957
  while (pos < end) {
3837
3958
  value = buf[pos++];
3838
3959
  if (value < 128)
@@ -3844,6 +3965,8 @@ Reader.prototype.bools = function read_bools(array) {
3844
3965
  }
3845
3966
  }
3846
3967
  this.pos = pos;
3968
+ if (pos !== end) throw RangeError("index out of range");
3969
+ this.len = len;
3847
3970
  return array;
3848
3971
  };
3849
3972
 
@@ -3866,7 +3989,7 @@ function getLazyView(reader, count, threshold) {
3866
3989
  */
3867
3990
  Reader.prototype.fixed32s = function read_fixed32s(array) {
3868
3991
  if (array === undefined) array = [];
3869
- var len = this.uint32(), end = this.pos + len;
3992
+ var len = this.size(), end = this.pos + len;
3870
3993
  /* istanbul ignore if */
3871
3994
  if (end > this.len) throw indexOutOfRange(this, len);
3872
3995
  var count = len >>> 2, i = array.length, pos = this.pos;
@@ -3890,7 +4013,7 @@ Reader.prototype.fixed32s = function read_fixed32s(array) {
3890
4013
  */
3891
4014
  Reader.prototype.sfixed32s = function read_sfixed32s(array) {
3892
4015
  if (array === undefined) array = [];
3893
- var len = this.uint32(), end = this.pos + len;
4016
+ var len = this.size(), end = this.pos + len;
3894
4017
  /* istanbul ignore if */
3895
4018
  if (end > this.len) throw indexOutOfRange(this, len);
3896
4019
  var count = len >>> 2, i = array.length, pos = this.pos;
@@ -3914,7 +4037,7 @@ Reader.prototype.sfixed32s = function read_sfixed32s(array) {
3914
4037
  */
3915
4038
  Reader.prototype.floats = function read_floats(array) {
3916
4039
  if (array === undefined) array = [];
3917
- var len = this.uint32(), end = this.pos + len;
4040
+ var len = this.size(), end = this.pos + len;
3918
4041
  /* istanbul ignore if */
3919
4042
  if (end > this.len) throw indexOutOfRange(this, len);
3920
4043
  var count = len >>> 2, i = array.length, pos = this.pos;
@@ -3938,7 +4061,7 @@ Reader.prototype.floats = function read_floats(array) {
3938
4061
  */
3939
4062
  Reader.prototype.doubles = function read_doubles(array) {
3940
4063
  if (array === undefined) array = [];
3941
- var len = this.uint32(), end = this.pos + len;
4064
+ var len = this.size(), end = this.pos + len;
3942
4065
  /* istanbul ignore if */
3943
4066
  if (end > this.len) throw indexOutOfRange(this, len);
3944
4067
  var count = len >>> 3, i = array.length, pos = this.pos;
@@ -3962,9 +4085,13 @@ Reader.prototype.doubles = function read_doubles(array) {
3962
4085
  */
3963
4086
  Reader.prototype.uint64s = function read_uint64s(array) {
3964
4087
  if (array === undefined) array = [];
3965
- var end = this.uint32() + this.pos;
4088
+ var end = this.size() + this.pos, len = this.len;
4089
+ if (end > len) throw indexOutOfRange(this, end - this.pos);
4090
+ this.len = end;
3966
4091
  while (this.pos < end)
3967
4092
  array.push(this.uint64());
4093
+ if (this.pos !== end) throw RangeError("index out of range");
4094
+ this.len = len;
3968
4095
  return array;
3969
4096
  };
3970
4097
 
@@ -3975,9 +4102,13 @@ Reader.prototype.uint64s = function read_uint64s(array) {
3975
4102
  */
3976
4103
  Reader.prototype.int64s = function read_int64s(array) {
3977
4104
  if (array === undefined) array = [];
3978
- var end = this.uint32() + this.pos;
4105
+ var end = this.size() + this.pos, len = this.len;
4106
+ if (end > len) throw indexOutOfRange(this, end - this.pos);
4107
+ this.len = end;
3979
4108
  while (this.pos < end)
3980
4109
  array.push(this.int64());
4110
+ if (this.pos !== end) throw RangeError("index out of range");
4111
+ this.len = len;
3981
4112
  return array;
3982
4113
  };
3983
4114
 
@@ -3988,9 +4119,13 @@ Reader.prototype.int64s = function read_int64s(array) {
3988
4119
  */
3989
4120
  Reader.prototype.sint64s = function read_sint64s(array) {
3990
4121
  if (array === undefined) array = [];
3991
- var end = this.uint32() + this.pos;
4122
+ var end = this.size() + this.pos, len = this.len;
4123
+ if (end > len) throw indexOutOfRange(this, end - this.pos);
4124
+ this.len = end;
3992
4125
  while (this.pos < end)
3993
4126
  array.push(this.sint64());
4127
+ if (this.pos !== end) throw RangeError("index out of range");
4128
+ this.len = len;
3994
4129
  return array;
3995
4130
  };
3996
4131
 
@@ -4001,7 +4136,7 @@ Reader.prototype.sint64s = function read_sint64s(array) {
4001
4136
  */
4002
4137
  Reader.prototype.fixed64s = function read_fixed64s(array) {
4003
4138
  if (array === undefined) array = [];
4004
- var len = this.uint32(), end = this.pos + len, i = array.length;
4139
+ var len = this.size(), end = this.pos + len, i = array.length;
4005
4140
  /* istanbul ignore if */
4006
4141
  if (end > this.len) throw indexOutOfRange(this, len);
4007
4142
  var count = len >>> 3;
@@ -4019,7 +4154,7 @@ Reader.prototype.fixed64s = function read_fixed64s(array) {
4019
4154
  */
4020
4155
  Reader.prototype.sfixed64s = function read_sfixed64s(array) {
4021
4156
  if (array === undefined) array = [];
4022
- var len = this.uint32(), end = this.pos + len, i = array.length;
4157
+ var len = this.size(), end = this.pos + len, i = array.length;
4023
4158
  /* istanbul ignore if */
4024
4159
  if (end > this.len) throw indexOutOfRange(this, len);
4025
4160
  var count = len >>> 3;
@@ -4035,7 +4170,7 @@ Reader.prototype.sfixed64s = function read_sfixed64s(array) {
4035
4170
  * @returns {Uint8Array} Value read
4036
4171
  */
4037
4172
  Reader.prototype.bytes = function read_bytes() {
4038
- var length = this.uint32(),
4173
+ var length = this.size(),
4039
4174
  start = this.pos,
4040
4175
  end = this.pos + length;
4041
4176
 
@@ -4052,7 +4187,7 @@ Reader.prototype.bytes = function read_bytes() {
4052
4187
  * @returns {string} Value read
4053
4188
  */
4054
4189
  Reader.prototype.string = function read_string() {
4055
- var length = this.uint32(),
4190
+ var length = this.size(),
4056
4191
  start = this.pos,
4057
4192
  end = this.pos + length;
4058
4193
 
@@ -4069,7 +4204,7 @@ Reader.prototype.string = function read_string() {
4069
4204
  * @returns {string} Value read
4070
4205
  */
4071
4206
  Reader.prototype.stringVerify = function read_string_verify() {
4072
- var length = this.uint32(),
4207
+ var length = this.size(),
4073
4208
  start = this.pos,
4074
4209
  end = this.pos + length;
4075
4210
 
@@ -4135,7 +4270,7 @@ Reader.prototype.skipType = function(wireType, depth, fieldNumber) {
4135
4270
  this.skip(8);
4136
4271
  break;
4137
4272
  case 2:
4138
- this.skip(this.uint32());
4273
+ this.skip(this.size());
4139
4274
  break;
4140
4275
  case 3:
4141
4276
  while (true) {
@@ -4250,7 +4385,7 @@ BufferReader.prototype.raw = function read_raw_buffer(start, end) {
4250
4385
  * @override
4251
4386
  */
4252
4387
  BufferReader.prototype.string = function read_string_buffer() {
4253
- var len = this.uint32(), // modifies pos
4388
+ var len = this.size(), // modifies pos
4254
4389
  start = this.pos,
4255
4390
  end = this.pos + len;
4256
4391
 
@@ -5195,6 +5330,12 @@ function Type(name, options) {
5195
5330
  */
5196
5331
  this.group = undefined; // toJSON
5197
5332
 
5333
+ /**
5334
+ * Declared symbol visibility, if any.
5335
+ * @type {"local"|"export"|undefined}
5336
+ */
5337
+ this.visibility = undefined; // toJSON
5338
+
5198
5339
  /**
5199
5340
  * Cached fields by id.
5200
5341
  * @type {Object.<number,Field>|null}
@@ -5379,6 +5520,7 @@ function clearCache(type) {
5379
5520
  * @property {number[][]} [extensions] Extension ranges
5380
5521
  * @property {Array.<number[]|string>} [reserved] Reserved ranges
5381
5522
  * @property {boolean} [group=false] Whether a legacy group or not
5523
+ * @property {"local"|"export"} [visibility] Declared symbol visibility
5382
5524
  * @property {string|null} [comment] Message type comment
5383
5525
  */
5384
5526
 
@@ -5429,6 +5571,8 @@ Type.fromJSON = function fromJSON(name, json, depth) {
5429
5571
  type.reserved = json.reserved;
5430
5572
  if (json.group)
5431
5573
  type.group = true;
5574
+ if (json.visibility)
5575
+ type.visibility = json.visibility;
5432
5576
  if (json.comment)
5433
5577
  type.comment = json.comment;
5434
5578
  if (json.edition)
@@ -5453,6 +5597,7 @@ Type.prototype.toJSON = function toJSON(toJSONOptions) {
5453
5597
  "extensions" , this.extensions && this.extensions.length ? this.extensions : undefined,
5454
5598
  "reserved" , this.reserved && this.reserved.length ? this.reserved : undefined,
5455
5599
  "group" , this.group || undefined,
5600
+ "visibility" , this.visibility,
5456
5601
  "nested" , inherited && inherited.nested || undefined,
5457
5602
  "comment" , keepComments ? this.comment : undefined
5458
5603
  ]);
@@ -5715,7 +5860,7 @@ Type.prototype.decode = function decode_setup(reader, length) { // eslint-disabl
5715
5860
  Type.prototype.decodeDelimited = function decodeDelimited(reader) {
5716
5861
  if (!(reader instanceof Reader))
5717
5862
  reader = Reader.create(reader);
5718
- return this.decode(reader, reader.uint32());
5863
+ return this.decode(reader, reader.size());
5719
5864
  };
5720
5865
 
5721
5866
  /**
@@ -8416,6 +8561,10 @@ var Message = require(10),
8416
8561
  wrappers[".google.protobuf.Any"] = {
8417
8562
 
8418
8563
  fromObject: function(object, depth) {
8564
+ if (depth === undefined)
8565
+ depth = 0;
8566
+ if (depth > util.recursionLimit)
8567
+ throw Error("max depth exceeded");
8419
8568
 
8420
8569
  // unwrap value type if mapped
8421
8570
  if (object && object["@type"]) {
@@ -8433,7 +8582,7 @@ wrappers[".google.protobuf.Any"] = {
8433
8582
  }
8434
8583
  return this.create({
8435
8584
  type_url: type_url,
8436
- value: type.encode(type.fromObject(object, depth === undefined ? 1 : depth + 1)).finish()
8585
+ value: type.encode(type.fromObject(object, depth + 1)).finish()
8437
8586
  });
8438
8587
  }
8439
8588
  }