protobufjs 7.4.0 → 8.0.0-experimental
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/dist/light/protobuf.js +276 -64
- package/dist/light/protobuf.js.map +1 -1
- package/dist/light/protobuf.min.js +3 -3
- package/dist/light/protobuf.min.js.map +1 -1
- package/dist/minimal/protobuf.js +2 -2
- package/dist/minimal/protobuf.min.js +2 -2
- package/dist/protobuf.js +369 -108
- package/dist/protobuf.js.map +1 -1
- package/dist/protobuf.min.js +3 -3
- package/dist/protobuf.min.js.map +1 -1
- package/index.d.ts +63 -9
- package/package.json +1 -1
- package/src/decoder.js +8 -10
- package/src/encoder.js +1 -1
- package/src/enum.js +43 -0
- package/src/field.js +82 -27
- package/src/namespace.js +2 -1
- package/src/object.js +83 -3
- package/src/oneof.js +19 -0
- package/src/parse.js +92 -43
- package/src/root.js +27 -14
- package/src/service.js +2 -1
- package/src/type.js +5 -4
- package/src/util.js +1 -0
package/index.d.ts
CHANGED
|
@@ -179,9 +179,21 @@ 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
|
+
|
|
185
|
+
/** Unresolved values features, if any */
|
|
186
|
+
public _valuesProtoFeatures?: { [k: string]: { [k: string]: any } };
|
|
187
|
+
|
|
182
188
|
/** Reserved ranges, if any. */
|
|
183
189
|
public reserved: (number[]|string)[];
|
|
184
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Resolves value features
|
|
193
|
+
* @returns `this`
|
|
194
|
+
*/
|
|
195
|
+
public resolve(): Enum;
|
|
196
|
+
|
|
185
197
|
/**
|
|
186
198
|
* Constructs an enum from an enum descriptor.
|
|
187
199
|
* @param name Enum name
|
|
@@ -267,9 +279,24 @@ export class Field extends FieldBase {
|
|
|
267
279
|
*/
|
|
268
280
|
public static fromJSON(name: string, json: IField): Field;
|
|
269
281
|
|
|
270
|
-
/** Determines whether this field is
|
|
282
|
+
/** Determines whether this field is required. */
|
|
283
|
+
public readonly required: boolean;
|
|
284
|
+
|
|
285
|
+
/** Determines whether this field is not required. */
|
|
286
|
+
public readonly optional: boolean;
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Determines whether this field uses tag-delimited encoding. In proto2 this
|
|
290
|
+
* corresponded to group syntax.
|
|
291
|
+
*/
|
|
292
|
+
public readonly delimited: boolean;
|
|
293
|
+
|
|
294
|
+
/** Determines whether this field is packed. Only relevant when repeated. */
|
|
271
295
|
public readonly packed: boolean;
|
|
272
296
|
|
|
297
|
+
/** Determines whether this field tracks presence. */
|
|
298
|
+
public readonly hasPresence: boolean;
|
|
299
|
+
|
|
273
300
|
/**
|
|
274
301
|
* Field decorator (TypeScript).
|
|
275
302
|
* @param fieldId Field id
|
|
@@ -314,12 +341,6 @@ export class FieldBase extends ReflectionObject {
|
|
|
314
341
|
/** Extended type if different from parent. */
|
|
315
342
|
public extend?: string;
|
|
316
343
|
|
|
317
|
-
/** Whether this field is required. */
|
|
318
|
-
public required: boolean;
|
|
319
|
-
|
|
320
|
-
/** Whether this field is optional. */
|
|
321
|
-
public optional: boolean;
|
|
322
|
-
|
|
323
344
|
/** Whether this field is repeated. */
|
|
324
345
|
public repeated: boolean;
|
|
325
346
|
|
|
@@ -369,6 +390,14 @@ export class FieldBase extends ReflectionObject {
|
|
|
369
390
|
* @throws {Error} If any reference cannot be resolved
|
|
370
391
|
*/
|
|
371
392
|
public resolve(): Field;
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Infers field features from legacy syntax that may have been specified differently.
|
|
396
|
+
* in older editions.
|
|
397
|
+
* @param edition The edition this proto is on, or undefined if pre-editions
|
|
398
|
+
* @returns The feature values to override
|
|
399
|
+
*/
|
|
400
|
+
public _inferLegacyProtoFeatures(edition: (string|undefined)): object;
|
|
372
401
|
}
|
|
373
402
|
|
|
374
403
|
/** Field descriptor. */
|
|
@@ -877,6 +906,12 @@ export abstract class ReflectionObject {
|
|
|
877
906
|
/** Unique name within its namespace. */
|
|
878
907
|
public name: string;
|
|
879
908
|
|
|
909
|
+
/** Resolved Features. */
|
|
910
|
+
public _features: any;
|
|
911
|
+
|
|
912
|
+
/** Unresolved Features. */
|
|
913
|
+
public _protoFeatures: any;
|
|
914
|
+
|
|
880
915
|
/** Parent namespace. */
|
|
881
916
|
public parent: (Namespace|null);
|
|
882
917
|
|
|
@@ -919,6 +954,17 @@ export abstract class ReflectionObject {
|
|
|
919
954
|
*/
|
|
920
955
|
public resolve(): ReflectionObject;
|
|
921
956
|
|
|
957
|
+
/** Resolves child features from parent features */
|
|
958
|
+
public _resolveFeatures(): void;
|
|
959
|
+
|
|
960
|
+
/**
|
|
961
|
+
* Infers features from legacy syntax that may have been specified differently.
|
|
962
|
+
* in older editions.
|
|
963
|
+
* @param edition The edition this proto is on, or undefined if pre-editions
|
|
964
|
+
* @returns The feature values to override
|
|
965
|
+
*/
|
|
966
|
+
public _inferLegacyProtoFeatures(edition: (string|undefined)): object;
|
|
967
|
+
|
|
922
968
|
/**
|
|
923
969
|
* Gets an option value.
|
|
924
970
|
* @param name Option name
|
|
@@ -1010,6 +1056,13 @@ export class OneOf extends ReflectionObject {
|
|
|
1010
1056
|
*/
|
|
1011
1057
|
public remove(field: Field): OneOf;
|
|
1012
1058
|
|
|
1059
|
+
/**
|
|
1060
|
+
* Determines whether this field corresponds to a synthetic oneof created for
|
|
1061
|
+
* a proto3 optional field. No behavioral logic should depend on this, but it
|
|
1062
|
+
* can be relevant for reflection.
|
|
1063
|
+
*/
|
|
1064
|
+
public readonly isProto3Optional: boolean;
|
|
1065
|
+
|
|
1013
1066
|
/**
|
|
1014
1067
|
* OneOf decorator (TypeScript).
|
|
1015
1068
|
* @param fieldNames Field names
|
|
@@ -1255,7 +1308,7 @@ export class Root extends NamespaceBase {
|
|
|
1255
1308
|
|
|
1256
1309
|
/**
|
|
1257
1310
|
* Loads a namespace descriptor into a root namespace.
|
|
1258
|
-
* @param json
|
|
1311
|
+
* @param json Namespace descriptor
|
|
1259
1312
|
* @param [root] Root namespace, defaults to create a new one if omitted
|
|
1260
1313
|
* @returns Root namespace
|
|
1261
1314
|
*/
|
|
@@ -2194,9 +2247,10 @@ export namespace util {
|
|
|
2194
2247
|
* @param dst Destination object
|
|
2195
2248
|
* @param path dot '.' delimited path of the property to set
|
|
2196
2249
|
* @param value the value to set
|
|
2250
|
+
* @param overWrite whether or not to concatenate the values into an array or overwrite; defaults to false.
|
|
2197
2251
|
* @returns Destination object
|
|
2198
2252
|
*/
|
|
2199
|
-
function setProperty(dst: { [k: string]: any }, path: string, value: object): { [k: string]: any };
|
|
2253
|
+
function setProperty(dst: { [k: string]: any }, path: string, value: object, overWrite: boolean): { [k: string]: any };
|
|
2200
2254
|
|
|
2201
2255
|
/** Decorator root (TypeScript). */
|
|
2202
2256
|
let decorateRoot: Root;
|
package/package.json
CHANGED
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
|
-
|
|
26
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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,18 @@ 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
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Unresolved values features, if any
|
|
67
|
+
* @type {Object<string, Object<string, *>>|undefined}
|
|
68
|
+
*/
|
|
69
|
+
this._valuesProtoFeatures = {};
|
|
70
|
+
|
|
59
71
|
/**
|
|
60
72
|
* Reserved ranges, if any.
|
|
61
73
|
* @type {Array.<number[]|string>}
|
|
@@ -72,6 +84,22 @@ function Enum(name, values, options, comment, comments, valuesOptions) {
|
|
|
72
84
|
this.valuesById[ this.values[keys[i]] = values[keys[i]] ] = keys[i];
|
|
73
85
|
}
|
|
74
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Resolves value features
|
|
89
|
+
* @returns {Enum} `this`
|
|
90
|
+
*/
|
|
91
|
+
Enum.prototype.resolve = function resolve() {
|
|
92
|
+
ReflectionObject.prototype.resolve.call(this);
|
|
93
|
+
|
|
94
|
+
for (var key of Object.keys(this._valuesProtoFeatures)) {
|
|
95
|
+
var parentFeaturesCopy = Object.assign({}, this._features);
|
|
96
|
+
this._valuesFeatures[key] = Object.assign(parentFeaturesCopy, this._valuesProtoFeatures[key] || {});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return this;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
|
|
75
103
|
/**
|
|
76
104
|
* Enum descriptor.
|
|
77
105
|
* @interface IEnum
|
|
@@ -148,6 +176,21 @@ Enum.prototype.add = function add(name, id, comment, options) {
|
|
|
148
176
|
if (this.valuesOptions === undefined)
|
|
149
177
|
this.valuesOptions = {};
|
|
150
178
|
this.valuesOptions[name] = options || null;
|
|
179
|
+
|
|
180
|
+
for (var key of Object.keys(this.valuesOptions)) {
|
|
181
|
+
var features = Array.isArray(this.valuesOptions[key]) ? this.valuesOptions[key].find(x => {return Object.prototype.hasOwnProperty.call(x, "features");}) : this.valuesOptions[key] === "features";
|
|
182
|
+
if (features) {
|
|
183
|
+
this._valuesProtoFeatures[key] = features.features;
|
|
184
|
+
} else {
|
|
185
|
+
this._valuesProtoFeatures[key] = {};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
for (var enumValue of Object.keys(this.values)) {
|
|
191
|
+
if (!this._valuesProtoFeatures[enumValue]) {
|
|
192
|
+
this._valuesProtoFeatures[enumValue] = {};
|
|
193
|
+
}
|
|
151
194
|
}
|
|
152
195
|
|
|
153
196
|
this.comments[name] = comment || null;
|
package/src/field.js
CHANGED
|
@@ -105,18 +105,6 @@ function Field(name, id, type, rule, extend, options, comment) {
|
|
|
105
105
|
*/
|
|
106
106
|
this.extend = extend || undefined; // toJSON
|
|
107
107
|
|
|
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
108
|
/**
|
|
121
109
|
* Whether this field is repeated.
|
|
122
110
|
* @type {boolean}
|
|
@@ -183,13 +171,6 @@ function Field(name, id, type, rule, extend, options, comment) {
|
|
|
183
171
|
*/
|
|
184
172
|
this.declaringField = null;
|
|
185
173
|
|
|
186
|
-
/**
|
|
187
|
-
* Internally remembers whether this field is packed.
|
|
188
|
-
* @type {boolean|null}
|
|
189
|
-
* @private
|
|
190
|
-
*/
|
|
191
|
-
this._packed = null;
|
|
192
|
-
|
|
193
174
|
/**
|
|
194
175
|
* Comment for this field.
|
|
195
176
|
* @type {string|null}
|
|
@@ -198,17 +179,69 @@ function Field(name, id, type, rule, extend, options, comment) {
|
|
|
198
179
|
}
|
|
199
180
|
|
|
200
181
|
/**
|
|
201
|
-
* Determines whether this field is
|
|
182
|
+
* Determines whether this field is required.
|
|
183
|
+
* @name Field#required
|
|
184
|
+
* @type {boolean}
|
|
185
|
+
* @readonly
|
|
186
|
+
*/
|
|
187
|
+
Object.defineProperty(Field.prototype, "required", {
|
|
188
|
+
get: function() {
|
|
189
|
+
return this._features.field_presence === "LEGACY_REQUIRED";
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Determines whether this field is not required.
|
|
195
|
+
* @name Field#optional
|
|
196
|
+
* @type {boolean}
|
|
197
|
+
* @readonly
|
|
198
|
+
*/
|
|
199
|
+
Object.defineProperty(Field.prototype, "optional", {
|
|
200
|
+
get: function() {
|
|
201
|
+
return !this.required;
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Determines whether this field uses tag-delimited encoding. In proto2 this
|
|
207
|
+
* corresponded to group syntax.
|
|
208
|
+
* @name Field#delimited
|
|
209
|
+
* @type {boolean}
|
|
210
|
+
* @readonly
|
|
211
|
+
*/
|
|
212
|
+
Object.defineProperty(Field.prototype, "delimited", {
|
|
213
|
+
get: function() {
|
|
214
|
+
return this.resolvedType instanceof Type &&
|
|
215
|
+
this._features.message_encoding === "DELIMITED";
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Determines whether this field is packed. Only relevant when repeated.
|
|
202
221
|
* @name Field#packed
|
|
203
222
|
* @type {boolean}
|
|
204
223
|
* @readonly
|
|
205
224
|
*/
|
|
206
225
|
Object.defineProperty(Field.prototype, "packed", {
|
|
207
226
|
get: function() {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
227
|
+
return this._features.repeated_field_encoding === "PACKED";
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Determines whether this field tracks presence.
|
|
233
|
+
* @name Field#hasPresence
|
|
234
|
+
* @type {boolean}
|
|
235
|
+
* @readonly
|
|
236
|
+
*/
|
|
237
|
+
Object.defineProperty(Field.prototype, "hasPresence", {
|
|
238
|
+
get: function() {
|
|
239
|
+
if (this.repeated || this.map) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
return this.partOf || // oneofs
|
|
243
|
+
this.declaringField || this.extensionField || // extensions
|
|
244
|
+
this._features.field_presence !== "IMPLICIT";
|
|
212
245
|
}
|
|
213
246
|
});
|
|
214
247
|
|
|
@@ -216,8 +249,6 @@ Object.defineProperty(Field.prototype, "packed", {
|
|
|
216
249
|
* @override
|
|
217
250
|
*/
|
|
218
251
|
Field.prototype.setOption = function setOption(name, value, ifNotSet) {
|
|
219
|
-
if (name === "packed") // clear cached before setting
|
|
220
|
-
this._packed = null;
|
|
221
252
|
return ReflectionObject.prototype.setOption.call(this, name, value, ifNotSet);
|
|
222
253
|
};
|
|
223
254
|
|
|
@@ -284,7 +315,7 @@ Field.prototype.resolve = function resolve() {
|
|
|
284
315
|
|
|
285
316
|
// remove unnecessary options
|
|
286
317
|
if (this.options) {
|
|
287
|
-
if (this.options.packed
|
|
318
|
+
if (this.options.packed !== undefined && this.resolvedType && !(this.resolvedType instanceof Enum))
|
|
288
319
|
delete this.options.packed;
|
|
289
320
|
if (!Object.keys(this.options).length)
|
|
290
321
|
this.options = undefined;
|
|
@@ -322,6 +353,30 @@ Field.prototype.resolve = function resolve() {
|
|
|
322
353
|
return ReflectionObject.prototype.resolve.call(this);
|
|
323
354
|
};
|
|
324
355
|
|
|
356
|
+
/**
|
|
357
|
+
* Infers field features from legacy syntax that may have been specified differently.
|
|
358
|
+
* in older editions.
|
|
359
|
+
* @param {string|undefined} edition The edition this proto is on, or undefined if pre-editions
|
|
360
|
+
* @returns {object} The feature values to override
|
|
361
|
+
*/
|
|
362
|
+
Field.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(edition) {
|
|
363
|
+
if (edition) return {};
|
|
364
|
+
|
|
365
|
+
var features = {};
|
|
366
|
+
if (this.rule === "required") {
|
|
367
|
+
features.field_presence = "LEGACY_REQUIRED";
|
|
368
|
+
}
|
|
369
|
+
if (this.resolvedType instanceof Type && this.resolvedType.group) {
|
|
370
|
+
features.message_encoding = "DELIMITED";
|
|
371
|
+
}
|
|
372
|
+
if (this.getOption("packed") === true) {
|
|
373
|
+
features.repeated_field_encoding = "PACKED";
|
|
374
|
+
} else if (this.getOption("packed") === false) {
|
|
375
|
+
features.repeated_field_encoding = "EXPANDED";
|
|
376
|
+
}
|
|
377
|
+
return features;
|
|
378
|
+
};
|
|
379
|
+
|
|
325
380
|
/**
|
|
326
381
|
* Decorator function as returned by {@link Field.d} and {@link MapField.d} (TypeScript).
|
|
327
382
|
* @typedef FieldDecorator
|
package/src/namespace.js
CHANGED
|
@@ -302,12 +302,13 @@ Namespace.prototype.define = function define(path, json) {
|
|
|
302
302
|
*/
|
|
303
303
|
Namespace.prototype.resolveAll = function resolveAll() {
|
|
304
304
|
var nested = this.nestedArray, i = 0;
|
|
305
|
+
this.resolve();
|
|
305
306
|
while (i < nested.length)
|
|
306
307
|
if (nested[i] instanceof Namespace)
|
|
307
308
|
nested[i++].resolveAll();
|
|
308
309
|
else
|
|
309
310
|
nested[i++].resolve();
|
|
310
|
-
return this
|
|
311
|
+
return this;
|
|
311
312
|
};
|
|
312
313
|
|
|
313
314
|
/**
|
package/src/object.js
CHANGED
|
@@ -3,10 +3,17 @@ module.exports = ReflectionObject;
|
|
|
3
3
|
|
|
4
4
|
ReflectionObject.className = "ReflectionObject";
|
|
5
5
|
|
|
6
|
+
const OneOf = require("./oneof");
|
|
6
7
|
var util = require("./util");
|
|
7
8
|
|
|
8
9
|
var Root; // cyclic
|
|
9
10
|
|
|
11
|
+
/* eslint-disable no-warning-comments */
|
|
12
|
+
// TODO: Replace with embedded proto.
|
|
13
|
+
var editions2023Defaults = {enum_type: "OPEN", field_presence: "EXPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY"};
|
|
14
|
+
var proto2Defaults = {enum_type: "CLOSED", field_presence: "EXPLICIT", json_format: "LEGACY_BEST_EFFORT", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "EXPANDED", utf8_validation: "NONE"};
|
|
15
|
+
var proto3Defaults = {enum_type: "OPEN", field_presence: "IMPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY"};
|
|
16
|
+
|
|
10
17
|
/**
|
|
11
18
|
* Constructs a new reflection object instance.
|
|
12
19
|
* @classdesc Base class of all reflection objects.
|
|
@@ -41,6 +48,16 @@ function ReflectionObject(name, options) {
|
|
|
41
48
|
*/
|
|
42
49
|
this.name = name;
|
|
43
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Resolved Features.
|
|
53
|
+
*/
|
|
54
|
+
this._features = {};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Unresolved Features.
|
|
58
|
+
*/
|
|
59
|
+
this._protoFeatures = null;
|
|
60
|
+
|
|
44
61
|
/**
|
|
45
62
|
* Parent namespace.
|
|
46
63
|
* @type {Namespace|null}
|
|
@@ -146,11 +163,65 @@ ReflectionObject.prototype.onRemove = function onRemove(parent) {
|
|
|
146
163
|
ReflectionObject.prototype.resolve = function resolve() {
|
|
147
164
|
if (this.resolved)
|
|
148
165
|
return this;
|
|
149
|
-
if (this
|
|
150
|
-
this.
|
|
166
|
+
if (this instanceof Root || this.parent && this.parent.resolved) {
|
|
167
|
+
this._resolveFeatures();
|
|
168
|
+
this.resolved = true;
|
|
169
|
+
}
|
|
151
170
|
return this;
|
|
152
171
|
};
|
|
153
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Resolves child features from parent features
|
|
175
|
+
* @returns {undefined}
|
|
176
|
+
*/
|
|
177
|
+
ReflectionObject.prototype._resolveFeatures = function _resolveFeatures() {
|
|
178
|
+
var defaults = {};
|
|
179
|
+
|
|
180
|
+
var edition = this.root.getOption("edition");
|
|
181
|
+
if (this instanceof Root) {
|
|
182
|
+
if (this.root.getOption("syntax") === "proto3") {
|
|
183
|
+
defaults = Object.assign({}, proto3Defaults);
|
|
184
|
+
} else if (edition === "2023") {
|
|
185
|
+
defaults = Object.assign({}, editions2023Defaults);
|
|
186
|
+
} else {
|
|
187
|
+
defaults = Object.assign({}, proto2Defaults);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
var protoFeatures = Object.assign(Object.assign({}, this._protoFeatures), this._inferLegacyProtoFeatures(edition));
|
|
192
|
+
|
|
193
|
+
if (this instanceof Root) {
|
|
194
|
+
this._features = Object.assign(defaults, protoFeatures || {});
|
|
195
|
+
// fields in Oneofs aren't actually children of them, so we have to
|
|
196
|
+
// special-case it
|
|
197
|
+
} else if (this.partOf instanceof OneOf) {
|
|
198
|
+
var lexicalParentFeaturesCopy = Object.assign({}, this.partOf._features);
|
|
199
|
+
this._features = Object.assign(lexicalParentFeaturesCopy, protoFeatures || {});
|
|
200
|
+
} else if (this.declaringField) {
|
|
201
|
+
// Skip feature resolution of sister fields.
|
|
202
|
+
} else if (this.parent) {
|
|
203
|
+
var parentFeaturesCopy = Object.assign({}, this.parent._features);
|
|
204
|
+
this._features = Object.assign(parentFeaturesCopy, protoFeatures || {});
|
|
205
|
+
} else {
|
|
206
|
+
this._features = Object.assign({}, protoFeatures);
|
|
207
|
+
}
|
|
208
|
+
if (this.extensionField) {
|
|
209
|
+
// Sister fields should have the same features as their extensions.
|
|
210
|
+
this.extensionField._features = this._features;
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Infers features from legacy syntax that may have been specified differently.
|
|
216
|
+
* in older editions.
|
|
217
|
+
* @param {string|undefined} edition The edition this proto is on, or undefined if pre-editions
|
|
218
|
+
* @returns {object} The feature values to override
|
|
219
|
+
* @abstract
|
|
220
|
+
*/
|
|
221
|
+
ReflectionObject.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(/*edition*/) {
|
|
222
|
+
return {};
|
|
223
|
+
};
|
|
224
|
+
|
|
154
225
|
/**
|
|
155
226
|
* Gets an option value.
|
|
156
227
|
* @param {string} name Option name
|
|
@@ -186,6 +257,7 @@ ReflectionObject.prototype.setParsedOption = function setParsedOption(name, valu
|
|
|
186
257
|
if (!this.parsedOptions) {
|
|
187
258
|
this.parsedOptions = [];
|
|
188
259
|
}
|
|
260
|
+
var isFeature = /^features$/.test(name);
|
|
189
261
|
var parsedOptions = this.parsedOptions;
|
|
190
262
|
if (propName) {
|
|
191
263
|
// If setting a sub property of an option then try to merge it
|
|
@@ -195,10 +267,11 @@ ReflectionObject.prototype.setParsedOption = function setParsedOption(name, valu
|
|
|
195
267
|
});
|
|
196
268
|
if (opt) {
|
|
197
269
|
// If we found an existing option - just merge the property value
|
|
270
|
+
// (If it's a feature, will just write over)
|
|
198
271
|
var newValue = opt[name];
|
|
199
272
|
util.setProperty(newValue, propName, value);
|
|
200
273
|
} else {
|
|
201
|
-
// otherwise, create a new option, set
|
|
274
|
+
// otherwise, create a new option, set its property and add it to the list
|
|
202
275
|
opt = {};
|
|
203
276
|
opt[name] = util.setProperty({}, propName, value);
|
|
204
277
|
parsedOptions.push(opt);
|
|
@@ -209,6 +282,13 @@ ReflectionObject.prototype.setParsedOption = function setParsedOption(name, valu
|
|
|
209
282
|
newOpt[name] = value;
|
|
210
283
|
parsedOptions.push(newOpt);
|
|
211
284
|
}
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
if (isFeature) {
|
|
288
|
+
var features = parsedOptions.find(x => {return Object.prototype.hasOwnProperty.call(x, "features");});
|
|
289
|
+
this._protoFeatures = features.features || {};
|
|
290
|
+
}
|
|
291
|
+
|
|
212
292
|
return this;
|
|
213
293
|
};
|
|
214
294
|
|
package/src/oneof.js
CHANGED
|
@@ -171,6 +171,25 @@ OneOf.prototype.onRemove = function onRemove(parent) {
|
|
|
171
171
|
ReflectionObject.prototype.onRemove.call(this, parent);
|
|
172
172
|
};
|
|
173
173
|
|
|
174
|
+
/**
|
|
175
|
+
* Determines whether this field corresponds to a synthetic oneof created for
|
|
176
|
+
* a proto3 optional field. No behavioral logic should depend on this, but it
|
|
177
|
+
* can be relevant for reflection.
|
|
178
|
+
* @name OneOf#isProto3Optional
|
|
179
|
+
* @type {boolean}
|
|
180
|
+
* @readonly
|
|
181
|
+
*/
|
|
182
|
+
Object.defineProperty(OneOf.prototype, "isProto3Optional", {
|
|
183
|
+
get: function() {
|
|
184
|
+
if (this.fieldsArray == null || this.fieldsArray.length !== 1) {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
var field = this.fieldsArray[0];
|
|
189
|
+
return field.options != null && field.options["proto3_optional"] === true;
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
174
193
|
/**
|
|
175
194
|
* Decorator function as returned by {@link OneOf.d} (TypeScript).
|
|
176
195
|
* @typedef OneOfDecorator
|