protobufjs 7.4.0 → 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/dist/light/protobuf.js +384 -70
- 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 +520 -134
- 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 +77 -13
- package/package.json +1 -1
- package/src/decoder.js +8 -10
- package/src/encoder.js +1 -1
- package/src/enum.js +25 -0
- package/src/field.js +98 -28
- package/src/namespace.js +24 -1
- package/src/object.js +127 -6
- package/src/oneof.js +19 -0
- package/src/parse.js +135 -63
- package/src/root.js +31 -15
- package/src/service.js +19 -1
- package/src/type.js +25 -4
- package/src/util.js +4 -1
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,25 @@ function ReflectionObject(name, options) {
|
|
|
41
48
|
*/
|
|
42
49
|
this.name = name;
|
|
43
50
|
|
|
51
|
+
/**
|
|
52
|
+
* The edition specified for this object. Only relevant for top-level objects.
|
|
53
|
+
* @type {string}
|
|
54
|
+
*/
|
|
55
|
+
this._edition = null;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The default edition to use for this object if none is specified. For legacy reasons,
|
|
59
|
+
* this is proto2 except in the JSON parsing case where it was proto3.
|
|
60
|
+
* @type {string}
|
|
61
|
+
*/
|
|
62
|
+
this._defaultEdition = "proto2";
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Resolved Features.
|
|
66
|
+
* @type {object}
|
|
67
|
+
*/
|
|
68
|
+
this._features = {};
|
|
69
|
+
|
|
44
70
|
/**
|
|
45
71
|
* Parent namespace.
|
|
46
72
|
* @type {Namespace|null}
|
|
@@ -146,11 +172,84 @@ ReflectionObject.prototype.onRemove = function onRemove(parent) {
|
|
|
146
172
|
ReflectionObject.prototype.resolve = function resolve() {
|
|
147
173
|
if (this.resolved)
|
|
148
174
|
return this;
|
|
149
|
-
if (this
|
|
150
|
-
this.
|
|
175
|
+
if (this instanceof Root) {
|
|
176
|
+
this._resolveFeaturesRecursive(this._edition);
|
|
177
|
+
this.resolved = true;
|
|
178
|
+
}
|
|
151
179
|
return this;
|
|
152
180
|
};
|
|
153
181
|
|
|
182
|
+
/**
|
|
183
|
+
* Resolves this objects editions features.
|
|
184
|
+
* @param {string} edition The edition we're currently resolving for.
|
|
185
|
+
* @returns {ReflectionObject} `this`
|
|
186
|
+
*/
|
|
187
|
+
ReflectionObject.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
|
|
188
|
+
return this._resolveFeatures(this._edition || edition);
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Resolves child features from parent features
|
|
193
|
+
* @param {string} edition The edition we're currently resolving for.
|
|
194
|
+
* @returns {undefined}
|
|
195
|
+
*/
|
|
196
|
+
ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition) {
|
|
197
|
+
var defaults = {};
|
|
198
|
+
|
|
199
|
+
/* istanbul ignore if */
|
|
200
|
+
if (!edition) {
|
|
201
|
+
throw new Error("Unknown edition for " + this.fullName);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
var protoFeatures = Object.assign(this.options ? Object.assign({}, this.options.features) : {},
|
|
205
|
+
this._inferLegacyProtoFeatures(edition));
|
|
206
|
+
|
|
207
|
+
if (this._edition) {
|
|
208
|
+
// For a namespace marked with a specific edition, reset defaults.
|
|
209
|
+
/* istanbul ignore else */
|
|
210
|
+
if (edition === "proto2") {
|
|
211
|
+
defaults = Object.assign({}, proto2Defaults);
|
|
212
|
+
} else if (edition === "proto3") {
|
|
213
|
+
defaults = Object.assign({}, proto3Defaults);
|
|
214
|
+
} else if (edition === "2023") {
|
|
215
|
+
defaults = Object.assign({}, editions2023Defaults);
|
|
216
|
+
} else {
|
|
217
|
+
throw new Error("Unknown edition: " + edition);
|
|
218
|
+
}
|
|
219
|
+
this._features = Object.assign(defaults, protoFeatures || {});
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// fields in Oneofs aren't actually children of them, so we have to
|
|
224
|
+
// special-case it
|
|
225
|
+
/* istanbul ignore else */
|
|
226
|
+
if (this.partOf instanceof OneOf) {
|
|
227
|
+
var lexicalParentFeaturesCopy = Object.assign({}, this.partOf._features);
|
|
228
|
+
this._features = Object.assign(lexicalParentFeaturesCopy, protoFeatures || {});
|
|
229
|
+
} else if (this.declaringField) {
|
|
230
|
+
// Skip feature resolution of sister fields.
|
|
231
|
+
} else if (this.parent) {
|
|
232
|
+
var parentFeaturesCopy = Object.assign({}, this.parent._features);
|
|
233
|
+
this._features = Object.assign(parentFeaturesCopy, protoFeatures || {});
|
|
234
|
+
} else {
|
|
235
|
+
throw new Error("Unable to find a parent for " + this.fullName);
|
|
236
|
+
}
|
|
237
|
+
if (this.extensionField) {
|
|
238
|
+
// Sister fields should have the same features as their extensions.
|
|
239
|
+
this.extensionField._features = this._features;
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Infers features from legacy syntax that may have been specified differently.
|
|
245
|
+
* in older editions.
|
|
246
|
+
* @param {string|undefined} edition The edition this proto is on, or undefined if pre-editions
|
|
247
|
+
* @returns {object} The feature values to override
|
|
248
|
+
*/
|
|
249
|
+
ReflectionObject.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(/*edition*/) {
|
|
250
|
+
return {};
|
|
251
|
+
};
|
|
252
|
+
|
|
154
253
|
/**
|
|
155
254
|
* Gets an option value.
|
|
156
255
|
* @param {string} name Option name
|
|
@@ -166,12 +265,19 @@ ReflectionObject.prototype.getOption = function getOption(name) {
|
|
|
166
265
|
* Sets an option.
|
|
167
266
|
* @param {string} name Option name
|
|
168
267
|
* @param {*} value Option value
|
|
169
|
-
* @param {boolean} [ifNotSet] Sets the option only if it isn't currently set
|
|
268
|
+
* @param {boolean|undefined} [ifNotSet] Sets the option only if it isn't currently set
|
|
170
269
|
* @returns {ReflectionObject} `this`
|
|
171
270
|
*/
|
|
172
271
|
ReflectionObject.prototype.setOption = function setOption(name, value, ifNotSet) {
|
|
173
|
-
if (!
|
|
174
|
-
|
|
272
|
+
if (!this.options)
|
|
273
|
+
this.options = {};
|
|
274
|
+
if (/^features\./.test(name)) {
|
|
275
|
+
util.setProperty(this.options, name, value, ifNotSet);
|
|
276
|
+
} else if (!ifNotSet || this.options[name] === undefined) {
|
|
277
|
+
if (this.getOption(name) !== value) this.resolved = false;
|
|
278
|
+
this.options[name] = value;
|
|
279
|
+
}
|
|
280
|
+
|
|
175
281
|
return this;
|
|
176
282
|
};
|
|
177
283
|
|
|
@@ -195,10 +301,11 @@ ReflectionObject.prototype.setParsedOption = function setParsedOption(name, valu
|
|
|
195
301
|
});
|
|
196
302
|
if (opt) {
|
|
197
303
|
// If we found an existing option - just merge the property value
|
|
304
|
+
// (If it's a feature, will just write over)
|
|
198
305
|
var newValue = opt[name];
|
|
199
306
|
util.setProperty(newValue, propName, value);
|
|
200
307
|
} else {
|
|
201
|
-
// otherwise, create a new option, set
|
|
308
|
+
// otherwise, create a new option, set its property and add it to the list
|
|
202
309
|
opt = {};
|
|
203
310
|
opt[name] = util.setProperty({}, propName, value);
|
|
204
311
|
parsedOptions.push(opt);
|
|
@@ -209,6 +316,7 @@ ReflectionObject.prototype.setParsedOption = function setParsedOption(name, valu
|
|
|
209
316
|
newOpt[name] = value;
|
|
210
317
|
parsedOptions.push(newOpt);
|
|
211
318
|
}
|
|
319
|
+
|
|
212
320
|
return this;
|
|
213
321
|
};
|
|
214
322
|
|
|
@@ -237,6 +345,19 @@ ReflectionObject.prototype.toString = function toString() {
|
|
|
237
345
|
return className;
|
|
238
346
|
};
|
|
239
347
|
|
|
348
|
+
/**
|
|
349
|
+
* Converts the edition this object is pinned to for JSON format.
|
|
350
|
+
* @returns {string|undefined} The edition string for JSON representation
|
|
351
|
+
*/
|
|
352
|
+
ReflectionObject.prototype._editionToJSON = function _editionToJSON() {
|
|
353
|
+
if (!this._edition || this._edition === "proto3") {
|
|
354
|
+
// Avoid emitting proto3 since we need to default to it for backwards
|
|
355
|
+
// compatibility anyway.
|
|
356
|
+
return undefined;
|
|
357
|
+
}
|
|
358
|
+
return this._edition;
|
|
359
|
+
};
|
|
360
|
+
|
|
240
361
|
// Sets up cyclic dependencies (called in index-light)
|
|
241
362
|
ReflectionObject._configure = function(Root_) {
|
|
242
363
|
Root = Root_;
|
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
|
package/src/parse.js
CHANGED
|
@@ -13,6 +13,7 @@ var tokenize = require("./tokenize"),
|
|
|
13
13
|
Enum = require("./enum"),
|
|
14
14
|
Service = require("./service"),
|
|
15
15
|
Method = require("./method"),
|
|
16
|
+
ReflectionObject = require("./object"),
|
|
16
17
|
types = require("./types"),
|
|
17
18
|
util = require("./util");
|
|
18
19
|
|
|
@@ -24,8 +25,7 @@ var base10Re = /^[1-9][0-9]*$/,
|
|
|
24
25
|
base8NegRe = /^-?0[0-7]+$/,
|
|
25
26
|
numberRe = /^(?![eE])[0-9]*(?:\.[0-9]*)?(?:[eE][+-]?[0-9]+)?$/,
|
|
26
27
|
nameRe = /^[a-zA-Z_][a-zA-Z_0-9]*$/,
|
|
27
|
-
typeRefRe = /^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)(?:\.[a-zA-Z_][a-zA-Z_0-9]*)
|
|
28
|
-
fqTypeRefRe = /^(?:\.[a-zA-Z_][a-zA-Z_0-9]*)+$/;
|
|
28
|
+
typeRefRe = /^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*$/;
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Result object returned from {@link parse}.
|
|
@@ -33,7 +33,6 @@ var base10Re = /^[1-9][0-9]*$/,
|
|
|
33
33
|
* @property {string|undefined} package Package name, if declared
|
|
34
34
|
* @property {string[]|undefined} imports Imports, if any
|
|
35
35
|
* @property {string[]|undefined} weakImports Weak imports, if any
|
|
36
|
-
* @property {string|undefined} syntax Syntax, if specified (either `"proto2"` or `"proto3"`)
|
|
37
36
|
* @property {Root} root Populated root instance
|
|
38
37
|
*/
|
|
39
38
|
|
|
@@ -81,13 +80,25 @@ function parse(source, root, options) {
|
|
|
81
80
|
pkg,
|
|
82
81
|
imports,
|
|
83
82
|
weakImports,
|
|
84
|
-
|
|
85
|
-
isProto3 = false;
|
|
83
|
+
edition = "proto2";
|
|
86
84
|
|
|
87
85
|
var ptr = root;
|
|
88
86
|
|
|
87
|
+
var topLevelObjects = [];
|
|
88
|
+
var topLevelOptions = {};
|
|
89
|
+
|
|
89
90
|
var applyCase = options.keepCase ? function(name) { return name; } : util.camelCase;
|
|
90
91
|
|
|
92
|
+
function resolveFileFeatures() {
|
|
93
|
+
topLevelObjects.forEach(obj => {
|
|
94
|
+
obj._edition = edition;
|
|
95
|
+
Object.keys(topLevelOptions).forEach(opt => {
|
|
96
|
+
if (obj.getOption(opt) !== undefined) return;
|
|
97
|
+
obj.setOption(opt, topLevelOptions[opt], true);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
91
102
|
/* istanbul ignore next */
|
|
92
103
|
function illegal(token, name, insideTryCatch) {
|
|
93
104
|
var filename = parse.filename;
|
|
@@ -126,7 +137,6 @@ function parse(source, root, options) {
|
|
|
126
137
|
try {
|
|
127
138
|
return parseNumber(token, /* insideTryCatch */ true);
|
|
128
139
|
} catch (e) {
|
|
129
|
-
|
|
130
140
|
/* istanbul ignore else */
|
|
131
141
|
if (acceptTypeRef && typeRefRe.test(token))
|
|
132
142
|
return token;
|
|
@@ -139,10 +149,23 @@ function parse(source, root, options) {
|
|
|
139
149
|
function readRanges(target, acceptStrings) {
|
|
140
150
|
var token, start;
|
|
141
151
|
do {
|
|
142
|
-
if (acceptStrings && ((token = peek()) === "\"" || token === "'"))
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
152
|
+
if (acceptStrings && ((token = peek()) === "\"" || token === "'")) {
|
|
153
|
+
var str = readString();
|
|
154
|
+
target.push(str);
|
|
155
|
+
if (edition >= 2023) {
|
|
156
|
+
throw illegal(str, "id");
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
try {
|
|
160
|
+
target.push([ start = parseId(next()), skip("to", true) ? parseId(next()) : start ]);
|
|
161
|
+
} catch (err) {
|
|
162
|
+
if (acceptStrings && typeRefRe.test(token) && edition >= 2023) {
|
|
163
|
+
target.push(token);
|
|
164
|
+
} else {
|
|
165
|
+
throw err;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
146
169
|
} while (skip(",", true));
|
|
147
170
|
var dummy = {options: undefined};
|
|
148
171
|
dummy.setOption = function(name, value) {
|
|
@@ -219,7 +242,6 @@ function parse(source, root, options) {
|
|
|
219
242
|
}
|
|
220
243
|
|
|
221
244
|
function parsePackage() {
|
|
222
|
-
|
|
223
245
|
/* istanbul ignore if */
|
|
224
246
|
if (pkg !== undefined)
|
|
225
247
|
throw illegal("package");
|
|
@@ -231,6 +253,7 @@ function parse(source, root, options) {
|
|
|
231
253
|
throw illegal(pkg, "name");
|
|
232
254
|
|
|
233
255
|
ptr = ptr.define(pkg);
|
|
256
|
+
|
|
234
257
|
skip(";");
|
|
235
258
|
}
|
|
236
259
|
|
|
@@ -256,20 +279,28 @@ function parse(source, root, options) {
|
|
|
256
279
|
|
|
257
280
|
function parseSyntax() {
|
|
258
281
|
skip("=");
|
|
259
|
-
|
|
260
|
-
isProto3 = syntax === "proto3";
|
|
282
|
+
edition = readString();
|
|
261
283
|
|
|
262
284
|
/* istanbul ignore if */
|
|
263
|
-
if (
|
|
264
|
-
throw illegal(
|
|
285
|
+
if (edition < 2023)
|
|
286
|
+
throw illegal(edition, "syntax");
|
|
265
287
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
288
|
+
skip(";");
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function parseEdition() {
|
|
292
|
+
skip("=");
|
|
293
|
+
edition = readString();
|
|
294
|
+
const supportedEditions = ["2023"];
|
|
295
|
+
|
|
296
|
+
/* istanbul ignore if */
|
|
297
|
+
if (!supportedEditions.includes(edition))
|
|
298
|
+
throw illegal(edition, "edition");
|
|
269
299
|
|
|
270
300
|
skip(";");
|
|
271
301
|
}
|
|
272
302
|
|
|
303
|
+
|
|
273
304
|
function parseCommon(parent, token) {
|
|
274
305
|
switch (token) {
|
|
275
306
|
|
|
@@ -337,14 +368,19 @@ function parse(source, root, options) {
|
|
|
337
368
|
break;
|
|
338
369
|
|
|
339
370
|
case "required":
|
|
371
|
+
if (edition !== "proto2")
|
|
372
|
+
throw illegal(token);
|
|
373
|
+
/* eslint-disable no-fallthrough */
|
|
340
374
|
case "repeated":
|
|
341
375
|
parseField(type, token);
|
|
342
376
|
break;
|
|
343
377
|
|
|
344
378
|
case "optional":
|
|
345
379
|
/* istanbul ignore if */
|
|
346
|
-
if (
|
|
380
|
+
if (edition === "proto3") {
|
|
347
381
|
parseField(type, "proto3_optional");
|
|
382
|
+
} else if (edition !== "proto2") {
|
|
383
|
+
throw illegal(token);
|
|
348
384
|
} else {
|
|
349
385
|
parseField(type, "optional");
|
|
350
386
|
}
|
|
@@ -364,8 +400,9 @@ function parse(source, root, options) {
|
|
|
364
400
|
|
|
365
401
|
default:
|
|
366
402
|
/* istanbul ignore if */
|
|
367
|
-
if (
|
|
403
|
+
if (edition === "proto2" || !typeRefRe.test(token)) {
|
|
368
404
|
throw illegal(token);
|
|
405
|
+
}
|
|
369
406
|
|
|
370
407
|
push(token);
|
|
371
408
|
parseField(type, "optional");
|
|
@@ -373,6 +410,9 @@ function parse(source, root, options) {
|
|
|
373
410
|
}
|
|
374
411
|
});
|
|
375
412
|
parent.add(type);
|
|
413
|
+
if (parent === ptr) {
|
|
414
|
+
topLevelObjects.push(type);
|
|
415
|
+
}
|
|
376
416
|
}
|
|
377
417
|
|
|
378
418
|
function parseField(parent, rule, extend) {
|
|
@@ -399,6 +439,7 @@ function parse(source, root, options) {
|
|
|
399
439
|
var name = next();
|
|
400
440
|
|
|
401
441
|
/* istanbul ignore if */
|
|
442
|
+
|
|
402
443
|
if (!nameRe.test(name))
|
|
403
444
|
throw illegal(name, "name");
|
|
404
445
|
|
|
@@ -406,6 +447,7 @@ function parse(source, root, options) {
|
|
|
406
447
|
skip("=");
|
|
407
448
|
|
|
408
449
|
var field = new Field(name, parseId(next()), type, rule, extend);
|
|
450
|
+
|
|
409
451
|
ifBlock(field, function parseField_block(token) {
|
|
410
452
|
|
|
411
453
|
/* istanbul ignore else */
|
|
@@ -428,15 +470,15 @@ function parse(source, root, options) {
|
|
|
428
470
|
} else {
|
|
429
471
|
parent.add(field);
|
|
430
472
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
// all known packable types and anything that could be an enum (= is not a basic type).
|
|
435
|
-
if (!isProto3 && field.repeated && (types.packed[type] !== undefined || types.basic[type] === undefined))
|
|
436
|
-
field.setOption("packed", false, /* ifNotSet */ true);
|
|
473
|
+
if (parent === ptr) {
|
|
474
|
+
topLevelObjects.push(field);
|
|
475
|
+
}
|
|
437
476
|
}
|
|
438
477
|
|
|
439
478
|
function parseGroup(parent, rule) {
|
|
479
|
+
if (edition >= 2023) {
|
|
480
|
+
throw illegal("group");
|
|
481
|
+
}
|
|
440
482
|
var name = next();
|
|
441
483
|
|
|
442
484
|
/* istanbul ignore if */
|
|
@@ -459,7 +501,6 @@ function parse(source, root, options) {
|
|
|
459
501
|
parseOption(type, token);
|
|
460
502
|
skip(";");
|
|
461
503
|
break;
|
|
462
|
-
|
|
463
504
|
case "required":
|
|
464
505
|
case "repeated":
|
|
465
506
|
parseField(type, token);
|
|
@@ -467,7 +508,7 @@ function parse(source, root, options) {
|
|
|
467
508
|
|
|
468
509
|
case "optional":
|
|
469
510
|
/* istanbul ignore if */
|
|
470
|
-
if (
|
|
511
|
+
if (edition === "proto3") {
|
|
471
512
|
parseField(type, "proto3_optional");
|
|
472
513
|
} else {
|
|
473
514
|
parseField(type, "optional");
|
|
@@ -565,6 +606,7 @@ function parse(source, root, options) {
|
|
|
565
606
|
|
|
566
607
|
case "reserved":
|
|
567
608
|
readRanges(enm.reserved || (enm.reserved = []), true);
|
|
609
|
+
if(enm.reserved === undefined) enm.reserved = [];
|
|
568
610
|
break;
|
|
569
611
|
|
|
570
612
|
default:
|
|
@@ -572,6 +614,9 @@ function parse(source, root, options) {
|
|
|
572
614
|
}
|
|
573
615
|
});
|
|
574
616
|
parent.add(enm);
|
|
617
|
+
if (parent === ptr) {
|
|
618
|
+
topLevelObjects.push(enm);
|
|
619
|
+
}
|
|
575
620
|
}
|
|
576
621
|
|
|
577
622
|
function parseEnumValue(parent, token) {
|
|
@@ -585,10 +630,14 @@ function parse(source, root, options) {
|
|
|
585
630
|
dummy = {
|
|
586
631
|
options: undefined
|
|
587
632
|
};
|
|
633
|
+
dummy.getOption = function(name) {
|
|
634
|
+
return this.options[name];
|
|
635
|
+
};
|
|
588
636
|
dummy.setOption = function(name, value) {
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
637
|
+
ReflectionObject.prototype.setOption.call(dummy, name, value);
|
|
638
|
+
};
|
|
639
|
+
dummy.setParsedOption = function() {
|
|
640
|
+
return undefined;
|
|
592
641
|
};
|
|
593
642
|
ifBlock(dummy, function parseEnumValue_block(token) {
|
|
594
643
|
|
|
@@ -602,34 +651,42 @@ function parse(source, root, options) {
|
|
|
602
651
|
}, function parseEnumValue_line() {
|
|
603
652
|
parseInlineOptions(dummy); // skip
|
|
604
653
|
});
|
|
605
|
-
parent.add(token, value, dummy.comment, dummy.options);
|
|
654
|
+
parent.add(token, value, dummy.comment, dummy.parsedOptions || dummy.options);
|
|
606
655
|
}
|
|
607
656
|
|
|
608
657
|
function parseOption(parent, token) {
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
var name = token;
|
|
616
|
-
var option = name;
|
|
617
|
-
var propName;
|
|
658
|
+
var option;
|
|
659
|
+
var propName;
|
|
660
|
+
var isOption = true;
|
|
661
|
+
if (token === "option") {
|
|
662
|
+
token = next();
|
|
663
|
+
}
|
|
618
664
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
665
|
+
while (token !== "=") {
|
|
666
|
+
if (token === "(") {
|
|
667
|
+
var parensValue = next();
|
|
668
|
+
skip(")");
|
|
669
|
+
token = "(" + parensValue + ")";
|
|
670
|
+
}
|
|
671
|
+
if (isOption) {
|
|
672
|
+
isOption = false;
|
|
673
|
+
if (token.includes(".") && !token.includes("(")) {
|
|
674
|
+
var tokens = token.split(".");
|
|
675
|
+
option = tokens[0] + ".";
|
|
676
|
+
token = tokens[1];
|
|
677
|
+
continue;
|
|
678
|
+
}
|
|
679
|
+
option = token;
|
|
680
|
+
} else {
|
|
681
|
+
propName = propName ? propName += token : token;
|
|
682
|
+
}
|
|
683
|
+
token = next();
|
|
628
684
|
}
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
685
|
+
var name = propName ? option.concat(propName) : option;
|
|
686
|
+
var optionValue = parseOptionValue(parent, name);
|
|
687
|
+
propName = propName && propName[0] === "." ? propName.slice(1) : propName;
|
|
688
|
+
option = option && option[option.length - 1] === "." ? option.slice(0, -1) : option;
|
|
689
|
+
setParsedOption(parent, option, optionValue, propName);
|
|
633
690
|
}
|
|
634
691
|
|
|
635
692
|
function parseOptionValue(parent, name) {
|
|
@@ -651,12 +708,12 @@ function parse(source, root, options) {
|
|
|
651
708
|
|
|
652
709
|
skip(":", true);
|
|
653
710
|
|
|
654
|
-
if (peek() === "{")
|
|
655
|
-
value = parseOptionValue(parent, name + "." + token);
|
|
656
|
-
else if (peek() === "[") {
|
|
711
|
+
if (peek() === "{") {
|
|
657
712
|
// option (my_option) = {
|
|
658
713
|
// repeated_value: [ "foo", "bar" ]
|
|
659
714
|
// };
|
|
715
|
+
value = parseOptionValue(parent, name + "." + token);
|
|
716
|
+
} else if (peek() === "[") {
|
|
660
717
|
value = [];
|
|
661
718
|
var lastValue;
|
|
662
719
|
if (skip("[", true)) {
|
|
@@ -696,6 +753,10 @@ function parse(source, root, options) {
|
|
|
696
753
|
}
|
|
697
754
|
|
|
698
755
|
function setOption(parent, name, value) {
|
|
756
|
+
if (ptr === parent && /^features\./.test(name)) {
|
|
757
|
+
topLevelOptions[name] = value;
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
699
760
|
if (parent.setOption)
|
|
700
761
|
parent.setOption(name, value);
|
|
701
762
|
}
|
|
@@ -723,8 +784,9 @@ function parse(source, root, options) {
|
|
|
723
784
|
|
|
724
785
|
var service = new Service(token);
|
|
725
786
|
ifBlock(service, function parseService_block(token) {
|
|
726
|
-
if (parseCommon(service, token))
|
|
787
|
+
if (parseCommon(service, token)) {
|
|
727
788
|
return;
|
|
789
|
+
}
|
|
728
790
|
|
|
729
791
|
/* istanbul ignore else */
|
|
730
792
|
if (token === "rpc")
|
|
@@ -733,6 +795,9 @@ function parse(source, root, options) {
|
|
|
733
795
|
throw illegal(token);
|
|
734
796
|
});
|
|
735
797
|
parent.add(service);
|
|
798
|
+
if (parent === ptr) {
|
|
799
|
+
topLevelObjects.push(service);
|
|
800
|
+
}
|
|
736
801
|
}
|
|
737
802
|
|
|
738
803
|
function parseMethod(parent, token) {
|
|
@@ -802,7 +867,7 @@ function parse(source, root, options) {
|
|
|
802
867
|
|
|
803
868
|
case "optional":
|
|
804
869
|
/* istanbul ignore if */
|
|
805
|
-
if (
|
|
870
|
+
if (edition === "proto3") {
|
|
806
871
|
parseField(parent, "proto3_optional", reference);
|
|
807
872
|
} else {
|
|
808
873
|
parseField(parent, "optional", reference);
|
|
@@ -811,7 +876,7 @@ function parse(source, root, options) {
|
|
|
811
876
|
|
|
812
877
|
default:
|
|
813
878
|
/* istanbul ignore if */
|
|
814
|
-
if (
|
|
879
|
+
if (edition === "proto2" || !typeRefRe.test(token))
|
|
815
880
|
throw illegal(token);
|
|
816
881
|
push(token);
|
|
817
882
|
parseField(parent, "optional", reference);
|
|
@@ -851,10 +916,16 @@ function parse(source, root, options) {
|
|
|
851
916
|
parseSyntax();
|
|
852
917
|
break;
|
|
853
918
|
|
|
854
|
-
case "
|
|
919
|
+
case "edition":
|
|
920
|
+
/* istanbul ignore if */
|
|
921
|
+
if (!head)
|
|
922
|
+
throw illegal(token);
|
|
923
|
+
parseEdition();
|
|
924
|
+
break;
|
|
855
925
|
|
|
926
|
+
case "option":
|
|
856
927
|
parseOption(ptr, token);
|
|
857
|
-
skip(";");
|
|
928
|
+
skip(";", true);
|
|
858
929
|
break;
|
|
859
930
|
|
|
860
931
|
default:
|
|
@@ -870,12 +941,13 @@ function parse(source, root, options) {
|
|
|
870
941
|
}
|
|
871
942
|
}
|
|
872
943
|
|
|
944
|
+
resolveFileFeatures();
|
|
945
|
+
|
|
873
946
|
parse.filename = null;
|
|
874
947
|
return {
|
|
875
948
|
"package" : pkg,
|
|
876
949
|
"imports" : imports,
|
|
877
950
|
weakImports : weakImports,
|
|
878
|
-
syntax : syntax,
|
|
879
951
|
root : root
|
|
880
952
|
};
|
|
881
953
|
}
|