protobufjs 8.6.1 → 8.6.3

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
@@ -100,6 +100,11 @@ export namespace common {
100
100
  value?: Uint8Array;
101
101
  }
102
102
 
103
+ /** Properties of a google.protobuf.FieldMask message. */
104
+ interface IFieldMask {
105
+ paths?: string[];
106
+ }
107
+
103
108
  /**
104
109
  * Gets the root definition of the specified common proto file.
105
110
  *
@@ -585,7 +590,7 @@ export class Message<T extends object = object> {
585
590
  */
586
591
  constructor(properties?: Properties<T>);
587
592
 
588
- /** Unknown fields preserved while decoding */
593
+ /** Unknown fields preserved while decoding when enabled */
589
594
  $unknowns?: Uint8Array[];
590
595
 
591
596
  /** Reference to the reflected type. */
@@ -1340,6 +1345,12 @@ export class Reader {
1340
1345
  */
1341
1346
  string(): string;
1342
1347
 
1348
+ /**
1349
+ * Reads a string preceeded by its byte length as a varint, rejecting invalid UTF8.
1350
+ * @returns Value read
1351
+ */
1352
+ stringVerify(): string;
1353
+
1343
1354
  /**
1344
1355
  * Skips the specified number of bytes if specified, otherwise skips a varint.
1345
1356
  * @param [length] Length if known, otherwise a varint is assumed
@@ -1711,6 +1722,7 @@ export class Type extends NamespaceBase {
1711
1722
  /**
1712
1723
  * The registered constructor, if any registered, otherwise a generic constructor.
1713
1724
  * Assigning a function replaces the internal constructor. If the function does not extend {@link Message} yet, its prototype will be setup accordingly and static methods will be populated. If it already extends {@link Message}, it will just replace the internal constructor.
1725
+ * When assigning manually, add the type to its parent namespace/root first if fields reference other reflected types, because constructor setup resolves field defaults.
1714
1726
  */
1715
1727
  ctor: Constructor<{}>;
1716
1728
 
@@ -2633,6 +2645,15 @@ export namespace util {
2633
2645
  */
2634
2646
  function read(buffer: Uint8Array, start: number, end: number): string;
2635
2647
 
2648
+ /**
2649
+ * Reads UTF8 bytes as a string, rejecting invalid UTF8.
2650
+ * @param buffer Source buffer
2651
+ * @param start Source start
2652
+ * @param end Source end
2653
+ * @returns String read
2654
+ */
2655
+ function readStrict(buffer: Uint8Array, start: number, end: number): string;
2656
+
2636
2657
  /**
2637
2658
  * Writes a string as UTF8 bytes.
2638
2659
  * @param string Source string
@@ -2660,6 +2681,15 @@ export namespace util {
2660
2681
  */
2661
2682
  function toObject(array: any[]): { [k: string]: any };
2662
2683
 
2684
+ /**
2685
+ * Removes the first matching value from an object.
2686
+ * @param object Object to remove from
2687
+ * @param value Value to remove
2688
+ * @param [key] Optional key for fast path removal
2689
+ * @returns `true` if removed, otherwise `false`
2690
+ */
2691
+ function remove(object: ({ [k: string]: any }|undefined), value: any, key?: string): boolean;
2692
+
2663
2693
  /**
2664
2694
  * Tests whether the specified name is a reserved word in JS.
2665
2695
  * @param name Name to test
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "protobufjs",
3
- "version": "8.6.1",
3
+ "version": "8.6.3",
4
4
  "description": "Protocol Buffers for JavaScript & TypeScript.",
5
5
  "author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
6
6
  "license": "BSD-3-Clause",
package/src/common.js CHANGED
@@ -363,9 +363,9 @@ common("field_mask", {
363
363
 
364
364
  /**
365
365
  * Properties of a google.protobuf.FieldMask message.
366
- * @interface IDoubleValue
366
+ * @interface IFieldMask
367
367
  * @type {Object}
368
- * @property {number} [value]
368
+ * @property {string[]} [paths]
369
369
  * @memberof common
370
370
  */
371
371
  FieldMask: {
package/src/decoder.js CHANGED
@@ -9,6 +9,10 @@ function missing(field) {
9
9
  return "missing required '" + field.name + "'";
10
10
  }
11
11
 
12
+ function stringMethod(field) {
13
+ return field._features.utf8_validation === "VERIFY" ? "stringVerify" : "string";
14
+ }
15
+
12
16
  /**
13
17
  * Generates a decoder specific to the specified message type.
14
18
  * @param {Type} mtype Message type
@@ -78,7 +82,7 @@ function decoder(mtype) {
78
82
  ("case 1:")
79
83
  ("if(u!==%i)", types.mapKey[field.keyType])
80
84
  ("break")
81
- ("k=r.%s()", field.keyType)
85
+ ("k=r.%s()", field.keyType === "string" ? stringMethod(field) : field.keyType)
82
86
  ("continue")
83
87
  ("case 2:")
84
88
  ("if(u!==%i)", types.basic[type] === undefined ? 2 : types.basic[type])
@@ -87,7 +91,7 @@ function decoder(mtype) {
87
91
  if (types.basic[type] === undefined) gen
88
92
  ("v=types[%i].decode(r,r.uint32(),undefined,q+1)", i); // can't be groups
89
93
  else gen
90
- ("v=r.%s()", type);
94
+ ("v=r.%s()", type === "string" ? stringMethod(field) : type);
91
95
 
92
96
  gen
93
97
  ("continue")
@@ -134,7 +138,7 @@ function decoder(mtype) {
134
138
  else gen
135
139
  ("%s.push(types[%i].decode(r,r.uint32(),undefined,q+1))", ref, i);
136
140
  } else gen
137
- ("%s.push(r.%s())", ref, type);
141
+ ("%s.push(r.%s())", ref, type === "string" ? stringMethod(field) : type);
138
142
 
139
143
  // Non-repeated
140
144
  } else if (types.basic[type] === undefined) {
@@ -152,7 +156,7 @@ function decoder(mtype) {
152
156
  ("case %i:{", field.id)
153
157
  ("if(u!==%i)", types.basic[type])
154
158
  ("break")
155
- ("%s=r.%s()", ref, type);
159
+ ("%s=r.%s()", ref, type === "string" ? stringMethod(field) : type);
156
160
  } else {
157
161
  gen
158
162
  ("case %i:{", field.id)
@@ -162,7 +166,9 @@ function decoder(mtype) {
162
166
  // TODO: Protoc rejects open enums whose first value is not zero.
163
167
  // We should do the same, but for v8 this would be a regression.
164
168
  ("if((v=r.%s())!==%j)", type, field.typeDefault);
165
- else if (type === "string" || type === "bytes") gen
169
+ else if (type === "string") gen
170
+ ("if((v=r.%s()).length)", stringMethod(field));
171
+ else if (type === "bytes") gen
166
172
  ("if((v=r.%s()).length)", type);
167
173
  else if (types.long[type] !== undefined) gen
168
174
  ("if(typeof(v=r.%s())===\"object\"?v.low||v.high:v!==0)", type);
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
- var protobuf = module.exports = require("./index-minimal");
2
+ exports = module.exports = require("./index-minimal");
3
3
 
4
- protobuf.build = "light";
4
+ exports.build = "light";
5
5
 
6
6
  /**
7
7
  * A node-style callback as used by {@link load} and {@link Root#load}.
@@ -23,9 +23,9 @@ protobuf.build = "light";
23
23
  function load(filename, root, callback) {
24
24
  if (typeof root === "function") {
25
25
  callback = root;
26
- root = new protobuf.Root();
26
+ root = new exports.Root();
27
27
  } else if (!root)
28
- root = new protobuf.Root();
28
+ root = new exports.Root();
29
29
  return root.load(filename, callback);
30
30
  }
31
31
 
@@ -53,7 +53,7 @@ function load(filename, root, callback) {
53
53
  */
54
54
  // function load(filename:string, [root:Root]):Promise<Root>
55
55
 
56
- protobuf.load = load;
56
+ exports.load = load;
57
57
 
58
58
  /**
59
59
  * Synchronously loads one or multiple .proto or preprocessed .json files into a common root namespace (node only).
@@ -65,40 +65,40 @@ protobuf.load = load;
65
65
  */
66
66
  function loadSync(filename, root) {
67
67
  if (!root)
68
- root = new protobuf.Root();
68
+ root = new exports.Root();
69
69
  return root.loadSync(filename);
70
70
  }
71
71
 
72
- protobuf.loadSync = loadSync;
72
+ exports.loadSync = loadSync;
73
73
 
74
74
  // Serialization
75
- protobuf.encoder = require("./encoder");
76
- protobuf.decoder = require("./decoder");
77
- protobuf.verifier = require("./verifier");
78
- protobuf.converter = require("./converter");
75
+ exports.encoder = require("./encoder");
76
+ exports.decoder = require("./decoder");
77
+ exports.verifier = require("./verifier");
78
+ exports.converter = require("./converter");
79
79
 
80
80
  // Reflection
81
- protobuf.ReflectionObject = require("./object");
82
- protobuf.Namespace = require("./namespace");
83
- protobuf.Root = require("./root");
84
- protobuf.Enum = require("./enum");
85
- protobuf.Type = require("./type");
86
- protobuf.Field = require("./field");
87
- protobuf.OneOf = require("./oneof");
88
- protobuf.MapField = require("./mapfield");
89
- protobuf.Service = require("./service");
90
- protobuf.Method = require("./method");
81
+ exports.ReflectionObject = require("./object");
82
+ exports.Namespace = require("./namespace");
83
+ exports.Root = require("./root");
84
+ exports.Enum = require("./enum");
85
+ exports.Type = require("./type");
86
+ exports.Field = require("./field");
87
+ exports.OneOf = require("./oneof");
88
+ exports.MapField = require("./mapfield");
89
+ exports.Service = require("./service");
90
+ exports.Method = require("./method");
91
91
 
92
92
  // Runtime
93
- protobuf.Message = require("./message");
94
- protobuf.wrappers = require("./wrappers");
93
+ exports.Message = require("./message");
94
+ exports.wrappers = require("./wrappers");
95
95
 
96
96
  // Utility
97
- protobuf.types = require("./types");
98
- protobuf.util = require("./util");
97
+ exports.types = require("./types");
98
+ exports.util = require("./util");
99
99
 
100
100
  // Set up possibly cyclic reflection dependencies
101
- protobuf.ReflectionObject._configure(protobuf.Root);
102
- protobuf.Namespace._configure(protobuf.Type, protobuf.Service, protobuf.Enum);
103
- protobuf.Root._configure(protobuf.Type, undefined, {});
104
- protobuf.Field._configure(protobuf.Type);
101
+ exports.ReflectionObject._configure(exports.Root);
102
+ exports.Namespace._configure(exports.Type, exports.Service, exports.Enum);
103
+ exports.Root._configure(exports.Type, undefined, {});
104
+ exports.Field._configure(exports.Type);
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
- var protobuf = exports;
3
2
 
4
3
  /**
5
4
  * Build type, one of `"full"`, `"light"` or `"minimal"`.
@@ -7,19 +6,19 @@ var protobuf = exports;
7
6
  * @type {string}
8
7
  * @const
9
8
  */
10
- protobuf.build = "minimal";
9
+ exports.build = "minimal";
11
10
 
12
11
  // Serialization
13
- protobuf.Writer = require("./writer");
14
- protobuf.BufferWriter = require("./writer_buffer");
15
- protobuf.Reader = require("./reader");
16
- protobuf.BufferReader = require("./reader_buffer");
12
+ exports.Writer = require("./writer");
13
+ exports.BufferWriter = require("./writer_buffer");
14
+ exports.Reader = require("./reader");
15
+ exports.BufferReader = require("./reader_buffer");
17
16
 
18
17
  // Utility
19
- protobuf.util = require("./util/minimal");
20
- protobuf.rpc = require("./rpc");
21
- protobuf.roots = require("./roots");
22
- protobuf.configure = configure;
18
+ exports.util = require("./util/minimal");
19
+ exports.rpc = require("./rpc");
20
+ exports.roots = require("./roots");
21
+ exports.configure = configure;
23
22
 
24
23
  /* istanbul ignore next */
25
24
  /**
@@ -27,9 +26,9 @@ protobuf.configure = configure;
27
26
  * @returns {undefined}
28
27
  */
29
28
  function configure() {
30
- protobuf.util._configure();
31
- protobuf.Writer._configure(protobuf.BufferWriter);
32
- protobuf.Reader._configure(protobuf.BufferReader);
29
+ exports.util._configure();
30
+ exports.Writer._configure(exports.BufferWriter);
31
+ exports.Reader._configure(exports.BufferReader);
33
32
  }
34
33
 
35
34
  // Set up buffer utility according to the environment
package/src/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
- var protobuf = module.exports = require("./index-light");
2
+ exports = module.exports = require("./index-light");
3
3
 
4
- protobuf.build = "full";
4
+ exports.build = "full";
5
5
 
6
6
  // Parser
7
- protobuf.tokenize = require("./tokenize");
8
- protobuf.parse = require("./parse");
9
- protobuf.common = require("./common");
7
+ exports.tokenize = require("./tokenize");
8
+ exports.parse = require("./parse");
9
+ exports.common = require("./common");
10
10
 
11
11
  // Configure parser
12
- protobuf.Root._configure(protobuf.Type, protobuf.parse, protobuf.common);
12
+ exports.Root._configure(exports.Type, exports.parse, exports.common);
package/src/message.js CHANGED
@@ -8,7 +8,7 @@ var util = require("./util/minimal");
8
8
  * @classdesc Abstract runtime message.
9
9
  * @constructor
10
10
  * @param {Properties<T>} [properties] Properties to set
11
- * @property {Array.<Uint8Array>} [$unknowns] Unknown fields preserved while decoding
11
+ * @property {Array.<Uint8Array>} [$unknowns] Unknown fields preserved while decoding when enabled
12
12
  * @template T extends object = object
13
13
  */
14
14
  function Message(properties) {
package/src/namespace.js CHANGED
@@ -321,7 +321,8 @@ Namespace.prototype.remove = function remove(object) {
321
321
  if (object.parent !== this)
322
322
  throw Error(object + " is not a member of " + this);
323
323
 
324
- delete this.nested[object.name];
324
+ if (!util.remove(this.nested, object, object.name))
325
+ throw Error(object + " is not a member of " + this);
325
326
  if (!Object.keys(this.nested).length)
326
327
  this.nested = undefined;
327
328
 
package/src/reader.js CHANGED
@@ -224,18 +224,16 @@ function readLongVarint() {
224
224
  return bits;
225
225
  i = 0;
226
226
  } else {
227
- for (; i < 3; ++i) {
227
+ for (; i < 4; ++i) {
228
228
  /* istanbul ignore if */
229
229
  if (this.pos >= this.len)
230
230
  throw indexOutOfRange(this);
231
- // 1st..3th
231
+ // 1st..4th
232
232
  bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0;
233
233
  if (this.buf[this.pos++] < 128)
234
234
  return bits;
235
235
  }
236
- // 4th
237
- bits.lo = (bits.lo | (this.buf[this.pos++] & 127) << i * 7) >>> 0;
238
- return bits;
236
+ throw indexOutOfRange(this);
239
237
  }
240
238
  if (this.len - this.pos > 4) { // fast route (hi)
241
239
  for (; i < 5; ++i) {
@@ -429,6 +427,23 @@ Reader.prototype.string = function read_string() {
429
427
  return utf8.read(this.buf, start, end);
430
428
  };
431
429
 
430
+ /**
431
+ * Reads a string preceeded by its byte length as a varint, rejecting invalid UTF8.
432
+ * @returns {string} Value read
433
+ */
434
+ Reader.prototype.stringVerify = function read_string_verify() {
435
+ var length = this.uint32(),
436
+ start = this.pos,
437
+ end = this.pos + length;
438
+
439
+ /* istanbul ignore if */
440
+ if (end > this.len)
441
+ throw indexOutOfRange(this, length);
442
+
443
+ this.pos = end;
444
+ return utf8.readStrict(this.buf, start, end);
445
+ };
446
+
432
447
  /**
433
448
  * Skips the specified number of bytes if specified, otherwise skips a varint.
434
449
  * @param {number} [length] Length if known, otherwise a varint is assumed
@@ -460,7 +475,7 @@ Reader.recursionLimit = util.recursionLimit;
460
475
  * Whether readers discard unknown fields while decoding.
461
476
  * @type {boolean}
462
477
  */
463
- Reader.discardUnknown = false;
478
+ Reader.discardUnknown = true;
464
479
 
465
480
  /**
466
481
  * Skips the next element of the specified wire type.
package/src/type.js CHANGED
@@ -155,6 +155,7 @@ Object.defineProperties(Type.prototype, {
155
155
  /**
156
156
  * The registered constructor, if any registered, otherwise a generic constructor.
157
157
  * Assigning a function replaces the internal constructor. If the function does not extend {@link Message} yet, its prototype will be setup accordingly and static methods will be populated. If it already extends {@link Message}, it will just replace the internal constructor.
158
+ * When assigning manually, add the type to its parent namespace/root first if fields reference other reflected types, because constructor setup resolves field defaults.
158
159
  * @name Type#ctor
159
160
  * @type {Constructor<{}>}
160
161
  */
@@ -424,10 +425,9 @@ Type.prototype.remove = function remove(object) {
424
425
  // See Type#add for the reason why extension fields are excluded here.
425
426
 
426
427
  /* istanbul ignore if */
427
- if (!this.fields || this.fields[object.name] !== object)
428
+ if (!util.remove(this.fields, object, object.name))
428
429
  throw Error(object + " is not a member of " + this);
429
430
 
430
- delete this.fields[object.name];
431
431
  object.parent = null;
432
432
  object.onRemove(this);
433
433
  return clearCache(this);
@@ -435,10 +435,9 @@ Type.prototype.remove = function remove(object) {
435
435
  if (object instanceof OneOf) {
436
436
 
437
437
  /* istanbul ignore if */
438
- if (!this.oneofs || this.oneofs[object.name] !== object)
438
+ if (!util.remove(this.oneofs, object, object.name))
439
439
  throw Error(object + " is not a member of " + this);
440
440
 
441
- delete this.oneofs[object.name];
442
441
  object.parent = null;
443
442
  object.onRemove(this);
444
443
  return clearCache(this);
package/src/util/path.js CHANGED
@@ -7,6 +7,28 @@
7
7
  */
8
8
  var path = exports;
9
9
 
10
+ var urlRe = /^[a-zA-Z][a-zA-Z0-9+.-]+:\/\//;
11
+
12
+ function normalizeUrl(path) {
13
+ if (typeof URL === "undefined" || !urlRe.test(path))
14
+ return null;
15
+ try {
16
+ return new URL(path).href;
17
+ } catch (e) {
18
+ return null;
19
+ }
20
+ }
21
+
22
+ function resolveUrl(originPath, includePath) {
23
+ if (typeof URL === "undefined" || !urlRe.test(originPath) || urlRe.test(includePath))
24
+ return null;
25
+ try {
26
+ return new URL(includePath, originPath).href;
27
+ } catch (e) {
28
+ return null;
29
+ }
30
+ }
31
+
10
32
  var isAbsolute =
11
33
  /**
12
34
  * Tests if the specified path is absolute.
@@ -24,6 +46,9 @@ var normalize =
24
46
  * @returns {string} Normalized path
25
47
  */
26
48
  path.normalize = function normalize(path) {
49
+ var normalizedUrl = normalizeUrl(path);
50
+ if (normalizedUrl)
51
+ return normalizedUrl;
27
52
  var firstTwoCharacters = path.substring(0,2);
28
53
  var uncPrefix = "";
29
54
  if (firstTwoCharacters === "\\\\") {
@@ -62,8 +87,11 @@ path.normalize = function normalize(path) {
62
87
  * @returns {string} Path to the include file
63
88
  */
64
89
  path.resolve = function resolve(originPath, includePath, alreadyNormalized) {
90
+ var resolvedUrl = resolveUrl(originPath, includePath);
91
+ if (resolvedUrl)
92
+ return resolvedUrl;
65
93
  if (!alreadyNormalized)
66
- includePath = normalize(includePath);
94
+ includePath = normalize(includePath); // path or absolute url
67
95
  if (isAbsolute(includePath))
68
96
  return includePath;
69
97
  if (!alreadyNormalized)
package/src/util/utf8.js CHANGED
@@ -6,7 +6,8 @@
6
6
  * @namespace
7
7
  */
8
8
  var utf8 = exports,
9
- replacementChar = "\ufffd";
9
+ replacementChar = "\ufffd",
10
+ strictDecoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
10
11
 
11
12
  /**
12
13
  * Calculates the UTF8 byte length of a string.
@@ -95,6 +96,56 @@ utf8.read = function utf8_read_ascii(buffer, start, end) {
95
96
  return str;
96
97
  };
97
98
 
99
+ function utf8_read_strict(buffer, start, end) {
100
+ var source = start === 0 && end === buffer.length
101
+ ? buffer
102
+ : buffer.subarray
103
+ ? buffer.subarray(start, end)
104
+ : buffer.slice(start, end);
105
+ if (Array.isArray(source))
106
+ source = Uint8Array.from(source);
107
+ return strictDecoder.decode(source);
108
+ }
109
+
110
+ /**
111
+ * Reads UTF8 bytes as a string, rejecting invalid UTF8.
112
+ * @param {Uint8Array} buffer Source buffer
113
+ * @param {number} start Source start
114
+ * @param {number} end Source end
115
+ * @returns {string} String read
116
+ */
117
+ utf8.readStrict = function utf8_read_strict_ascii(buffer, start, end) {
118
+ if (end - start < 1)
119
+ return "";
120
+
121
+ var str = "",
122
+ i = start,
123
+ c1, c2, c3, c4, c5, c6, c7, c8;
124
+
125
+ for (; i + 7 < end; i += 8) {
126
+ c1 = buffer[i];
127
+ c2 = buffer[i + 1];
128
+ c3 = buffer[i + 2];
129
+ c4 = buffer[i + 3];
130
+ c5 = buffer[i + 4];
131
+ c6 = buffer[i + 5];
132
+ c7 = buffer[i + 6];
133
+ c8 = buffer[i + 7];
134
+ if ((c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8) & 0x80)
135
+ return str + utf8_read_strict(buffer, i, end);
136
+ str += String.fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8);
137
+ }
138
+
139
+ for (; i < end; ++i) {
140
+ c1 = buffer[i];
141
+ if (c1 & 0x80)
142
+ return str + utf8_read_strict(buffer, i, end);
143
+ str += String.fromCharCode(c1);
144
+ }
145
+
146
+ return str;
147
+ };
148
+
98
149
  /**
99
150
  * Writes a string as UTF8 bytes.
100
151
  * @param {string} string Source string
package/src/util.js CHANGED
@@ -58,6 +58,28 @@ util.toObject = function toObject(array) {
58
58
  return object;
59
59
  };
60
60
 
61
+ /**
62
+ * Removes the first matching value from an object.
63
+ * @param {Object.<string,*>|undefined} object Object to remove from
64
+ * @param {*} value Value to remove
65
+ * @param {string} [key] Optional key for fast path removal
66
+ * @returns {boolean} `true` if removed, otherwise `false`
67
+ */
68
+ util.remove = function remove(object, value, key) {
69
+ if (!object)
70
+ return false;
71
+ if (key !== undefined && Object.prototype.hasOwnProperty.call(object, key) && object[key] === value) {
72
+ delete object[key];
73
+ return true;
74
+ }
75
+ for (var names = Object.keys(object), i = 0; i < names.length; ++i)
76
+ if (object[names[i]] === value) {
77
+ delete object[names[i]];
78
+ return true;
79
+ }
80
+ return false;
81
+ };
82
+
61
83
  /**
62
84
  * Tests whether the specified name is a reserved word in JS.
63
85
  * @param {string} name Name to test