protobufjs 7.3.3 → 7.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -179,6 +179,9 @@ export class Enum extends ReflectionObject {
179
179
  /** Values options, if any */
180
180
  public valuesOptions?: { [k: string]: { [k: string]: any } };
181
181
 
182
+ /** Resolved values features, if any */
183
+ public _valuesFeatures?: { [k: string]: { [k: string]: any } };
184
+
182
185
  /** Reserved ranges, if any. */
183
186
  public reserved: (number[]|string)[];
184
187
 
@@ -267,9 +270,24 @@ export class Field extends FieldBase {
267
270
  */
268
271
  public static fromJSON(name: string, json: IField): Field;
269
272
 
270
- /** Determines whether this field is packed. Only relevant when repeated and working with proto2. */
273
+ /** Determines whether this field is required. */
274
+ public readonly required: boolean;
275
+
276
+ /** Determines whether this field is not required. */
277
+ public readonly optional: boolean;
278
+
279
+ /**
280
+ * Determines whether this field uses tag-delimited encoding. In proto2 this
281
+ * corresponded to group syntax.
282
+ */
283
+ public readonly delimited: boolean;
284
+
285
+ /** Determines whether this field is packed. Only relevant when repeated. */
271
286
  public readonly packed: boolean;
272
287
 
288
+ /** Determines whether this field tracks presence. */
289
+ public readonly hasPresence: boolean;
290
+
273
291
  /**
274
292
  * Field decorator (TypeScript).
275
293
  * @param fieldId Field id
@@ -314,12 +332,6 @@ export class FieldBase extends ReflectionObject {
314
332
  /** Extended type if different from parent. */
315
333
  public extend?: string;
316
334
 
317
- /** Whether this field is required. */
318
- public required: boolean;
319
-
320
- /** Whether this field is optional. */
321
- public optional: boolean;
322
-
323
335
  /** Whether this field is repeated. */
324
336
  public repeated: boolean;
325
337
 
@@ -369,6 +381,14 @@ export class FieldBase extends ReflectionObject {
369
381
  * @throws {Error} If any reference cannot be resolved
370
382
  */
371
383
  public resolve(): Field;
384
+
385
+ /**
386
+ * Infers field features from legacy syntax that may have been specified differently.
387
+ * in older editions.
388
+ * @param edition The edition this proto is on, or undefined if pre-editions
389
+ * @returns The feature values to override
390
+ */
391
+ public _inferLegacyProtoFeatures(edition: (string|undefined)): object;
372
392
  }
373
393
 
374
394
  /** Field descriptor. */
@@ -877,6 +897,18 @@ export abstract class ReflectionObject {
877
897
  /** Unique name within its namespace. */
878
898
  public name: string;
879
899
 
900
+ /** The edition specified for this object. Only relevant for top-level objects. */
901
+ public _edition: string;
902
+
903
+ /**
904
+ * The default edition to use for this object if none is specified. For legacy reasons,
905
+ * this is proto2 except in the JSON parsing case where it was proto3.
906
+ */
907
+ public _defaultEdition: string;
908
+
909
+ /** Resolved Features. */
910
+ public _features: object;
911
+
880
912
  /** Parent namespace. */
881
913
  public parent: (Namespace|null);
882
914
 
@@ -919,6 +951,27 @@ export abstract class ReflectionObject {
919
951
  */
920
952
  public resolve(): ReflectionObject;
921
953
 
954
+ /**
955
+ * Resolves this objects editions features.
956
+ * @param edition The edition we're currently resolving for.
957
+ * @returns `this`
958
+ */
959
+ public _resolveFeaturesRecursive(edition: string): ReflectionObject;
960
+
961
+ /**
962
+ * Resolves child features from parent features
963
+ * @param edition The edition we're currently resolving for.
964
+ */
965
+ public _resolveFeatures(edition: string): void;
966
+
967
+ /**
968
+ * Infers features from legacy syntax that may have been specified differently.
969
+ * in older editions.
970
+ * @param edition The edition this proto is on, or undefined if pre-editions
971
+ * @returns The feature values to override
972
+ */
973
+ public _inferLegacyProtoFeatures(edition: (string|undefined)): object;
974
+
922
975
  /**
923
976
  * Gets an option value.
924
977
  * @param name Option name
@@ -933,7 +986,7 @@ export abstract class ReflectionObject {
933
986
  * @param [ifNotSet] Sets the option only if it isn't currently set
934
987
  * @returns `this`
935
988
  */
936
- public setOption(name: string, value: any, ifNotSet?: boolean): ReflectionObject;
989
+ public setOption(name: string, value: any, ifNotSet?: (boolean|undefined)): ReflectionObject;
937
990
 
938
991
  /**
939
992
  * Sets a parsed option.
@@ -957,6 +1010,12 @@ export abstract class ReflectionObject {
957
1010
  * @returns Class name[, space, full name]
958
1011
  */
959
1012
  public toString(): string;
1013
+
1014
+ /**
1015
+ * Converts the edition this object is pinned to for JSON format.
1016
+ * @returns The edition string for JSON representation
1017
+ */
1018
+ public _editionToJSON(): (string|undefined);
960
1019
  }
961
1020
 
962
1021
  /** Reflected oneof. */
@@ -1010,6 +1069,13 @@ export class OneOf extends ReflectionObject {
1010
1069
  */
1011
1070
  public remove(field: Field): OneOf;
1012
1071
 
1072
+ /**
1073
+ * Determines whether this field corresponds to a synthetic oneof created for
1074
+ * a proto3 optional field. No behavioral logic should depend on this, but it
1075
+ * can be relevant for reflection.
1076
+ */
1077
+ public readonly isProto3Optional: boolean;
1078
+
1013
1079
  /**
1014
1080
  * OneOf decorator (TypeScript).
1015
1081
  * @param fieldNames Field names
@@ -1055,9 +1121,6 @@ export interface IParserResult {
1055
1121
  /** Weak imports, if any */
1056
1122
  weakImports: (string[]|undefined);
1057
1123
 
1058
- /** Syntax, if specified (either `"proto2"` or `"proto3"`) */
1059
- syntax: (string|undefined);
1060
-
1061
1124
  /** Populated root instance */
1062
1125
  root: Root;
1063
1126
  }
@@ -1255,7 +1318,7 @@ export class Root extends NamespaceBase {
1255
1318
 
1256
1319
  /**
1257
1320
  * Loads a namespace descriptor into a root namespace.
1258
- * @param json Nameespace descriptor
1321
+ * @param json Namespace descriptor
1259
1322
  * @param [root] Root namespace, defaults to create a new one if omitted
1260
1323
  * @returns Root namespace
1261
1324
  */
@@ -2194,9 +2257,10 @@ export namespace util {
2194
2257
  * @param dst Destination object
2195
2258
  * @param path dot '.' delimited path of the property to set
2196
2259
  * @param value the value to set
2260
+ * @param [ifNotSet] Sets the option only if it isn't currently set
2197
2261
  * @returns Destination object
2198
2262
  */
2199
- function setProperty(dst: { [k: string]: any }, path: string, value: object): { [k: string]: any };
2263
+ function setProperty(dst: { [k: string]: any }, path: string, value: object, ifNotSet?: (boolean|undefined)): { [k: string]: any };
2200
2264
 
2201
2265
  /** Decorator root (TypeScript). */
2202
2266
  let decorateRoot: Root;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "protobufjs",
3
- "version": "7.3.3",
3
+ "version": "7.5.0",
4
4
  "versionScheme": "~",
5
5
  "description": "Protocol Buffers for JavaScript (& TypeScript).",
6
6
  "author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
@@ -40,6 +40,7 @@
40
40
  "lint:types": "tslint \"**/*.d.ts\" -e \"**/node_modules/**\" -t stylish -c config/tslint.json",
41
41
  "pages": "node scripts/pages",
42
42
  "prepublish": "cd cli && npm install && cd .. && npm run build",
43
+ "prepublishOnly": "cd cli && npm install && cd .. && npm run build",
43
44
  "postinstall": "node scripts/postinstall",
44
45
  "prof": "node bench/prof",
45
46
  "test": "npm run test:sources && npm run test:types",
package/src/decoder.js CHANGED
@@ -16,16 +16,14 @@ function missing(field) {
16
16
  */
17
17
  function decoder(mtype) {
18
18
  /* eslint-disable no-unexpected-multiline */
19
- var gen = util.codegen(["r", "l"], mtype.name + "$decode")
19
+ var gen = util.codegen(["r", "l", "e"], mtype.name + "$decode")
20
20
  ("if(!(r instanceof Reader))")
21
21
  ("r=Reader.create(r)")
22
22
  ("var c=l===undefined?r.len:r.pos+l,m=new this.ctor" + (mtype.fieldsArray.filter(function(field) { return field.map; }).length ? ",k,value" : ""))
23
23
  ("while(r.pos<c){")
24
- ("var t=r.uint32()");
25
- if (mtype.group) gen
26
- ("if((t&7)===4)")
27
- ("break");
28
- gen
24
+ ("var t=r.uint32()")
25
+ ("if(t===e)")
26
+ ("break")
29
27
  ("switch(t>>>3){");
30
28
 
31
29
  var i = 0;
@@ -91,15 +89,15 @@ function decoder(mtype) {
91
89
  ("}else");
92
90
 
93
91
  // Non-packed
94
- if (types.basic[type] === undefined) gen(field.resolvedType.group
95
- ? "%s.push(types[%i].decode(r))"
92
+ if (types.basic[type] === undefined) gen(field.delimited
93
+ ? "%s.push(types[%i].decode(r,undefined,((t&~7)|4)))"
96
94
  : "%s.push(types[%i].decode(r,r.uint32()))", ref, i);
97
95
  else gen
98
96
  ("%s.push(r.%s())", ref, type);
99
97
 
100
98
  // Non-repeated
101
- } else if (types.basic[type] === undefined) gen(field.resolvedType.group
102
- ? "%s=types[%i].decode(r)"
99
+ } else if (types.basic[type] === undefined) gen(field.delimited
100
+ ? "%s=types[%i].decode(r,undefined,((t&~7)|4))"
103
101
  : "%s=types[%i].decode(r,r.uint32())", ref, i);
104
102
  else gen
105
103
  ("%s=r.%s()", ref, type);
package/src/encoder.js CHANGED
@@ -15,7 +15,7 @@ var Enum = require("./enum"),
15
15
  * @ignore
16
16
  */
17
17
  function genTypePartial(gen, field, fieldIndex, ref) {
18
- return field.resolvedType.group
18
+ return field.delimited
19
19
  ? gen("types[%i].encode(%s,w.uint32(%i)).uint32(%i)", fieldIndex, ref, (field.id << 3 | 3) >>> 0, (field.id << 3 | 4) >>> 0)
20
20
  : gen("types[%i].encode(%s,w.uint32(%i).fork()).ldelim()", fieldIndex, ref, (field.id << 3 | 2) >>> 0);
21
21
  }
package/src/enum.js CHANGED
@@ -56,6 +56,12 @@ function Enum(name, values, options, comment, comments, valuesOptions) {
56
56
  */
57
57
  this.valuesOptions = valuesOptions;
58
58
 
59
+ /**
60
+ * Resolved values features, if any
61
+ * @type {Object<string, Object<string, *>>|undefined}
62
+ */
63
+ this._valuesFeatures = {};
64
+
59
65
  /**
60
66
  * Reserved ranges, if any.
61
67
  * @type {Array.<number[]|string>}
@@ -72,6 +78,21 @@ function Enum(name, values, options, comment, comments, valuesOptions) {
72
78
  this.valuesById[ this.values[keys[i]] = values[keys[i]] ] = keys[i];
73
79
  }
74
80
 
81
+ /**
82
+ * @override
83
+ */
84
+ Enum.prototype._resolveFeatures = function _resolveFeatures(edition) {
85
+ edition = this._edition || edition;
86
+ ReflectionObject.prototype._resolveFeatures.call(this, edition);
87
+
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);
91
+ });
92
+
93
+ return this;
94
+ };
95
+
75
96
  /**
76
97
  * Enum descriptor.
77
98
  * @interface IEnum
@@ -89,6 +110,9 @@ function Enum(name, values, options, comment, comments, valuesOptions) {
89
110
  Enum.fromJSON = function fromJSON(name, json) {
90
111
  var enm = new Enum(name, json.values, json.options, json.comment, json.comments);
91
112
  enm.reserved = json.reserved;
113
+ if (json.edition)
114
+ enm._edition = json.edition;
115
+ enm._defaultEdition = "proto3"; // For backwards-compatibility.
92
116
  return enm;
93
117
  };
94
118
 
@@ -100,6 +124,7 @@ Enum.fromJSON = function fromJSON(name, json) {
100
124
  Enum.prototype.toJSON = function toJSON(toJSONOptions) {
101
125
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
102
126
  return util.toObject([
127
+ "edition" , this._editionToJSON(),
103
128
  "options" , this.options,
104
129
  "valuesOptions" , this.valuesOptions,
105
130
  "values" , this.values,
package/src/field.js CHANGED
@@ -35,7 +35,11 @@ var ruleRe = /^required|optional|repeated$/;
35
35
  * @throws {TypeError} If arguments are invalid
36
36
  */
37
37
  Field.fromJSON = function fromJSON(name, json) {
38
- return new Field(name, json.id, json.type, json.rule, json.extend, json.options, json.comment);
38
+ var field = new Field(name, json.id, json.type, json.rule, json.extend, json.options, json.comment);
39
+ if (json.edition)
40
+ field._edition = json.edition;
41
+ field._defaultEdition = "proto3"; // For backwards-compatibility.
42
+ return field;
39
43
  };
40
44
 
41
45
  /**
@@ -105,18 +109,6 @@ function Field(name, id, type, rule, extend, options, comment) {
105
109
  */
106
110
  this.extend = extend || undefined; // toJSON
107
111
 
108
- /**
109
- * Whether this field is required.
110
- * @type {boolean}
111
- */
112
- this.required = rule === "required";
113
-
114
- /**
115
- * Whether this field is optional.
116
- * @type {boolean}
117
- */
118
- this.optional = !this.required;
119
-
120
112
  /**
121
113
  * Whether this field is repeated.
122
114
  * @type {boolean}
@@ -183,13 +175,6 @@ function Field(name, id, type, rule, extend, options, comment) {
183
175
  */
184
176
  this.declaringField = null;
185
177
 
186
- /**
187
- * Internally remembers whether this field is packed.
188
- * @type {boolean|null}
189
- * @private
190
- */
191
- this._packed = null;
192
-
193
178
  /**
194
179
  * Comment for this field.
195
180
  * @type {string|null}
@@ -198,17 +183,69 @@ function Field(name, id, type, rule, extend, options, comment) {
198
183
  }
199
184
 
200
185
  /**
201
- * Determines whether this field is packed. Only relevant when repeated and working with proto2.
186
+ * Determines whether this field is required.
187
+ * @name Field#required
188
+ * @type {boolean}
189
+ * @readonly
190
+ */
191
+ Object.defineProperty(Field.prototype, "required", {
192
+ get: function() {
193
+ return this._features.field_presence === "LEGACY_REQUIRED";
194
+ }
195
+ });
196
+
197
+ /**
198
+ * Determines whether this field is not required.
199
+ * @name Field#optional
200
+ * @type {boolean}
201
+ * @readonly
202
+ */
203
+ Object.defineProperty(Field.prototype, "optional", {
204
+ get: function() {
205
+ return !this.required;
206
+ }
207
+ });
208
+
209
+ /**
210
+ * Determines whether this field uses tag-delimited encoding. In proto2 this
211
+ * corresponded to group syntax.
212
+ * @name Field#delimited
213
+ * @type {boolean}
214
+ * @readonly
215
+ */
216
+ Object.defineProperty(Field.prototype, "delimited", {
217
+ get: function() {
218
+ return this.resolvedType instanceof Type &&
219
+ this._features.message_encoding === "DELIMITED";
220
+ }
221
+ });
222
+
223
+ /**
224
+ * Determines whether this field is packed. Only relevant when repeated.
202
225
  * @name Field#packed
203
226
  * @type {boolean}
204
227
  * @readonly
205
228
  */
206
229
  Object.defineProperty(Field.prototype, "packed", {
207
230
  get: function() {
208
- // defaults to packed=true if not explicity set to false
209
- if (this._packed === null)
210
- this._packed = this.getOption("packed") !== false;
211
- return this._packed;
231
+ return this._features.repeated_field_encoding === "PACKED";
232
+ }
233
+ });
234
+
235
+ /**
236
+ * Determines whether this field tracks presence.
237
+ * @name Field#hasPresence
238
+ * @type {boolean}
239
+ * @readonly
240
+ */
241
+ Object.defineProperty(Field.prototype, "hasPresence", {
242
+ get: function() {
243
+ if (this.repeated || this.map) {
244
+ return false;
245
+ }
246
+ return this.partOf || // oneofs
247
+ this.declaringField || this.extensionField || // extensions
248
+ this._features.field_presence !== "IMPLICIT";
212
249
  }
213
250
  });
214
251
 
@@ -216,8 +253,6 @@ Object.defineProperty(Field.prototype, "packed", {
216
253
  * @override
217
254
  */
218
255
  Field.prototype.setOption = function setOption(name, value, ifNotSet) {
219
- if (name === "packed") // clear cached before setting
220
- this._packed = null;
221
256
  return ReflectionObject.prototype.setOption.call(this, name, value, ifNotSet);
222
257
  };
223
258
 
@@ -245,6 +280,7 @@ Field.prototype.setOption = function setOption(name, value, ifNotSet) {
245
280
  Field.prototype.toJSON = function toJSON(toJSONOptions) {
246
281
  var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
247
282
  return util.toObject([
283
+ "edition" , this._editionToJSON(),
248
284
  "rule" , this.rule !== "optional" && this.rule || undefined,
249
285
  "type" , this.type,
250
286
  "id" , this.id,
@@ -284,7 +320,7 @@ Field.prototype.resolve = function resolve() {
284
320
 
285
321
  // remove unnecessary options
286
322
  if (this.options) {
287
- if (this.options.packed === true || this.options.packed !== undefined && this.resolvedType && !(this.resolvedType instanceof Enum))
323
+ if (this.options.packed !== undefined && this.resolvedType && !(this.resolvedType instanceof Enum))
288
324
  delete this.options.packed;
289
325
  if (!Object.keys(this.options).length)
290
326
  this.options = undefined;
@@ -322,6 +358,40 @@ Field.prototype.resolve = function resolve() {
322
358
  return ReflectionObject.prototype.resolve.call(this);
323
359
  };
324
360
 
361
+ /**
362
+ * Infers field features from legacy syntax that may have been specified differently.
363
+ * in older editions.
364
+ * @param {string|undefined} edition The edition this proto is on, or undefined if pre-editions
365
+ * @returns {object} The feature values to override
366
+ */
367
+ Field.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(edition) {
368
+ if (edition !== "proto2" && edition !== "proto3") {
369
+ return {};
370
+ }
371
+
372
+ var features = {};
373
+ this.resolve();
374
+ if (this.rule === "required") {
375
+ features.field_presence = "LEGACY_REQUIRED";
376
+ }
377
+ if (this.resolvedType instanceof Type && this.resolvedType.group) {
378
+ features.message_encoding = "DELIMITED";
379
+ }
380
+ if (this.getOption("packed") === true) {
381
+ features.repeated_field_encoding = "PACKED";
382
+ } else if (this.getOption("packed") === false) {
383
+ features.repeated_field_encoding = "EXPANDED";
384
+ }
385
+ return features;
386
+ };
387
+
388
+ /**
389
+ * @override
390
+ */
391
+ Field.prototype._resolveFeatures = function _resolveFeatures(edition) {
392
+ return ReflectionObject.prototype._resolveFeatures.call(this, this._edition || edition);
393
+ };
394
+
325
395
  /**
326
396
  * Decorator function as returned by {@link Field.d} and {@link MapField.d} (TypeScript).
327
397
  * @typedef FieldDecorator
package/src/namespace.js CHANGED
@@ -240,6 +240,15 @@ Namespace.prototype.add = function add(object) {
240
240
  }
241
241
  }
242
242
  this.nested[object.name] = object;
243
+
244
+ if (!(this instanceof Type || this instanceof Service || this instanceof Enum || this instanceof Field)) {
245
+ // This is a package or a root namespace.
246
+ if (!object._edition) {
247
+ // Make sure that some edition is set if it hasn't already been specified.
248
+ object._edition = object._defaultEdition;
249
+ }
250
+ }
251
+
243
252
  object.onAdd(this);
244
253
  return clearCache(this);
245
254
  };
@@ -302,12 +311,26 @@ Namespace.prototype.define = function define(path, json) {
302
311
  */
303
312
  Namespace.prototype.resolveAll = function resolveAll() {
304
313
  var nested = this.nestedArray, i = 0;
314
+ this.resolve();
305
315
  while (i < nested.length)
306
316
  if (nested[i] instanceof Namespace)
307
317
  nested[i++].resolveAll();
308
318
  else
309
319
  nested[i++].resolve();
310
- return this.resolve();
320
+ return this;
321
+ };
322
+
323
+ /**
324
+ * @override
325
+ */
326
+ Namespace.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
327
+ edition = this._edition || edition;
328
+
329
+ ReflectionObject.prototype._resolveFeaturesRecursive.call(this, edition);
330
+ this.nestedArray.forEach(nested => {
331
+ nested._resolveFeaturesRecursive(edition);
332
+ });
333
+ return this;
311
334
  };
312
335
 
313
336
  /**