protobufjs 8.6.0 → 8.6.2

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.
Files changed (108) hide show
  1. package/LICENSE +39 -39
  2. package/README.md +441 -441
  3. package/dist/light/protobuf.js +8473 -8516
  4. package/dist/light/protobuf.js.map +1 -1
  5. package/dist/light/protobuf.min.js +3 -3
  6. package/dist/light/protobuf.min.js.map +1 -1
  7. package/dist/minimal/protobuf.js +3018 -3061
  8. package/dist/minimal/protobuf.js.map +1 -1
  9. package/dist/minimal/protobuf.min.js +3 -3
  10. package/dist/minimal/protobuf.min.js.map +1 -1
  11. package/dist/protobuf.js +10376 -10419
  12. package/dist/protobuf.js.map +1 -1
  13. package/dist/protobuf.min.js +3 -3
  14. package/dist/protobuf.min.js.map +1 -1
  15. package/ext/README.md +70 -70
  16. package/ext/debug/README.md +4 -4
  17. package/ext/debug/index.js +71 -71
  18. package/ext/descriptor/README.md +5 -5
  19. package/ext/descriptor/index.d.ts +2 -2
  20. package/ext/descriptor/index.js +2 -2
  21. package/ext/descriptor.d.ts +87 -86
  22. package/ext/descriptor.generated.d.ts +14 -6
  23. package/ext/descriptor.js +1354 -1303
  24. package/ext/protojson.LICENSE +201 -201
  25. package/ext/protojson.d.ts +20 -20
  26. package/ext/protojson.js +925 -903
  27. package/ext/textformat.d.ts +19 -19
  28. package/ext/textformat.js +1256 -1256
  29. package/google/LICENSE +27 -27
  30. package/google/README.md +1 -1
  31. package/google/api/annotations.json +82 -82
  32. package/google/api/annotations.proto +10 -10
  33. package/google/api/http.json +85 -85
  34. package/google/api/http.proto +30 -30
  35. package/google/protobuf/api.json +117 -117
  36. package/google/protobuf/api.proto +33 -33
  37. package/google/protobuf/compiler/plugin.json +126 -126
  38. package/google/protobuf/compiler/plugin.proto +47 -47
  39. package/google/protobuf/descriptor.json +1381 -1381
  40. package/google/protobuf/descriptor.proto +534 -534
  41. package/google/protobuf/source_context.json +19 -19
  42. package/google/protobuf/source_context.proto +7 -7
  43. package/google/protobuf/type.json +201 -201
  44. package/google/protobuf/type.proto +89 -89
  45. package/index.d.ts +10 -18
  46. package/index.js +4 -4
  47. package/light.d.ts +2 -2
  48. package/light.js +3 -3
  49. package/minimal.d.ts +2 -2
  50. package/minimal.js +4 -4
  51. package/package.json +93 -93
  52. package/src/common.js +399 -399
  53. package/src/converter.js +344 -344
  54. package/src/decoder.js +208 -208
  55. package/src/encoder.js +111 -111
  56. package/src/enum.js +231 -231
  57. package/src/field.js +497 -497
  58. package/src/index-light.js +104 -104
  59. package/src/index-minimal.js +36 -36
  60. package/src/index.js +12 -12
  61. package/src/mapfield.js +136 -136
  62. package/src/message.js +137 -137
  63. package/src/method.js +175 -175
  64. package/src/namespace.js +565 -565
  65. package/src/object.js +382 -382
  66. package/src/oneof.js +225 -225
  67. package/src/parse.js +1068 -1068
  68. package/src/reader.js +543 -543
  69. package/src/reader_buffer.js +72 -72
  70. package/src/root.js +416 -416
  71. package/src/roots.js +18 -18
  72. package/src/rpc/service.js +148 -148
  73. package/src/rpc.js +36 -36
  74. package/src/service.js +198 -198
  75. package/src/tokenize.js +421 -421
  76. package/src/type.js +655 -655
  77. package/src/types.js +196 -196
  78. package/src/typescript.js +25 -25
  79. package/src/util/aspromise.d.ts +13 -13
  80. package/src/util/aspromise.js +52 -52
  81. package/src/util/base64.d.ts +32 -32
  82. package/src/util/base64.js +146 -146
  83. package/src/util/codegen.d.ts +31 -31
  84. package/src/util/codegen.js +113 -113
  85. package/src/util/eventemitter.d.ts +45 -45
  86. package/src/util/eventemitter.js +86 -86
  87. package/src/util/fetch.d.ts +56 -56
  88. package/src/util/fetch.js +112 -112
  89. package/src/util/float.d.ts +83 -83
  90. package/src/util/float.js +335 -335
  91. package/src/util/fs.js +11 -11
  92. package/src/util/longbits.js +200 -200
  93. package/src/util/minimal.js +515 -518
  94. package/src/util/path.d.ts +22 -22
  95. package/src/util/path.js +72 -72
  96. package/src/util/patterns.js +7 -7
  97. package/src/util/pool.d.ts +32 -32
  98. package/src/util/pool.js +48 -48
  99. package/src/util/utf8.d.ts +24 -24
  100. package/src/util/utf8.js +130 -130
  101. package/src/util.js +242 -242
  102. package/src/verifier.js +180 -180
  103. package/src/wrappers.js +106 -106
  104. package/src/writer.js +495 -495
  105. package/src/writer_buffer.js +102 -102
  106. package/tsconfig.json +6 -6
  107. package/src/util/inquire.d.ts +0 -10
  108. package/src/util/inquire.js +0 -38
package/src/parse.js CHANGED
@@ -1,1068 +1,1068 @@
1
- "use strict";
2
- module.exports = parse;
3
-
4
- parse.filename = null;
5
- parse.defaults = { keepCase: false };
6
-
7
- var tokenize = require("./tokenize"),
8
- Root = require("./root"),
9
- Type = require("./type"),
10
- Field = require("./field"),
11
- MapField = require("./mapfield"),
12
- OneOf = require("./oneof"),
13
- Enum = require("./enum"),
14
- Service = require("./service"),
15
- Method = require("./method"),
16
- ReflectionObject = require("./object"),
17
- types = require("./types"),
18
- util = require("./util");
19
-
20
- var base10Re = /^[1-9][0-9]*$/,
21
- base10NegRe = /^-?[1-9][0-9]*$/,
22
- base16Re = /^0[x][0-9a-fA-F]+$/,
23
- base16NegRe = /^-?0[x][0-9a-fA-F]+$/,
24
- base8Re = /^0[0-7]+$/,
25
- base8NegRe = /^-?0[0-7]+$/,
26
- numberRe = util.patterns.numberRe,
27
- nameRe = /^[a-zA-Z_][a-zA-Z_0-9]*$/,
28
- typeRefRe = util.patterns.typeRefRe;
29
-
30
- var maxFieldId = 536870911, // 2^29 - 1
31
- maxEnumId = 2147483647; // 2^31 - 1
32
-
33
- /**
34
- * Result object returned from {@link parse}.
35
- * @interface IParserResult
36
- * @property {string|undefined} package Package name, if declared
37
- * @property {string[]|undefined} imports Imports, if any
38
- * @property {string[]|undefined} weakImports Weak imports, if any
39
- * @property {Root} root Populated root instance
40
- */
41
-
42
- /**
43
- * Options modifying the behavior of {@link parse}.
44
- * @interface IParseOptions
45
- * @property {boolean} [keepCase=false] Keeps field casing instead of converting to camel case
46
- * @property {boolean} [alternateCommentMode=false] Recognize double-slash comments in addition to doc-block comments.
47
- * @property {boolean} [preferTrailingComment=false] Use trailing comment when both leading comment and trailing comment exist.
48
- */
49
-
50
- /**
51
- * Options modifying the behavior of JSON serialization.
52
- * @interface IToJSONOptions
53
- * @property {boolean} [keepComments=false] Serializes comments.
54
- */
55
-
56
- /**
57
- * Parses the given .proto source and returns an object with the parsed contents.
58
- * @param {string} source Source contents
59
- * @param {Root} root Root to populate
60
- * @param {IParseOptions} [options] Parse options. Defaults to {@link parse.defaults} when omitted.
61
- * @returns {IParserResult} Parser result
62
- * @property {string} filename=null Currently processing file name for error reporting, if known
63
- * @property {IParseOptions} defaults Default {@link IParseOptions}
64
- */
65
- function parse(source, root, options) {
66
- /* eslint-disable callback-return */
67
- if (!(root instanceof Root)) {
68
- options = root;
69
- root = new Root();
70
- }
71
- if (!options)
72
- options = parse.defaults;
73
-
74
- var preferTrailingComment = options.preferTrailingComment || false;
75
- var tn = tokenize(source, options.alternateCommentMode || false),
76
- next = tn.next,
77
- push = tn.push,
78
- peek = tn.peek,
79
- skip = tn.skip,
80
- cmnt = tn.cmnt;
81
-
82
- var head = true,
83
- pkg,
84
- imports,
85
- weakImports,
86
- edition = "proto2";
87
-
88
- var ptr = root;
89
-
90
- var topLevelObjects = [];
91
- var topLevelOptions = {};
92
-
93
- var applyCase = options.keepCase ? function(name) { return name; } : util.camelCase;
94
-
95
- function resolveFileFeatures() {
96
- topLevelObjects.forEach(obj => {
97
- obj._edition = edition;
98
- Object.keys(topLevelOptions).forEach(opt => {
99
- if (obj.getOption(opt) !== undefined) return;
100
- obj.setOption(opt, topLevelOptions[opt], true);
101
- });
102
- });
103
- }
104
-
105
- /* istanbul ignore next */
106
- function illegal(token, name, insideTryCatch) {
107
- var filename = parse.filename;
108
- if (!insideTryCatch)
109
- parse.filename = null;
110
- return Error("illegal " + (name || "token") + " '" + token + "' (" + (filename ? filename + ", " : "") + "line " + tn.line + ")");
111
- }
112
-
113
- function readString() {
114
- var values = [],
115
- token;
116
- do {
117
- /* istanbul ignore if */
118
- if ((token = next()) !== "\"" && token !== "'")
119
- throw illegal(token);
120
-
121
- values.push(next());
122
- skip(token);
123
- token = peek();
124
- } while (token === "\"" || token === "'");
125
- return values.join("");
126
- }
127
-
128
- function readValue(acceptTypeRef) {
129
- var token = next();
130
- switch (token) {
131
- case "'":
132
- case "\"":
133
- push(token);
134
- return readString();
135
- case "true": case "TRUE":
136
- return true;
137
- case "false": case "FALSE":
138
- return false;
139
- }
140
- try {
141
- return parseNumber(token, /* insideTryCatch */ true);
142
- } catch (e) {
143
- /* istanbul ignore else */
144
- if (acceptTypeRef && typeRefRe.test(token))
145
- return token;
146
-
147
- /* istanbul ignore next */
148
- throw illegal(token, "value");
149
- }
150
- }
151
-
152
- function readRanges(target, acceptStrings, max, acceptNegative) {
153
- var token, start;
154
- do {
155
- if (acceptStrings && ((token = peek()) === "\"" || token === "'")) {
156
- var str = readString();
157
- target.push(str);
158
- if (edition >= 2023) {
159
- throw illegal(str, "id");
160
- }
161
- } else {
162
- try {
163
- target.push([ start = parseId(next(), acceptNegative, max), skip("to", true) ? parseId(next(), acceptNegative, max) : start ]);
164
- } catch (err) {
165
- if (acceptStrings && typeRefRe.test(token) && edition >= 2023) {
166
- target.push(token);
167
- } else {
168
- throw err;
169
- }
170
- }
171
- }
172
- } while (skip(",", true));
173
- var dummy = {options: undefined};
174
- dummy.setOption = function(name, value) {
175
- if (this.options === undefined) this.options = {};
176
- this.options[name] = value;
177
- };
178
- ifBlock(
179
- dummy,
180
- function parseRange_block(token) {
181
- /* istanbul ignore else */
182
- if (token === "option") {
183
- parseOption(dummy, token); // skip
184
- skip(";");
185
- } else
186
- throw illegal(token);
187
- },
188
- function parseRange_line() {
189
- parseInlineOptions(dummy); // skip
190
- });
191
- }
192
-
193
- function parseNumber(token, insideTryCatch) {
194
- var sign = 1;
195
- if (token.charAt(0) === "-") {
196
- sign = -1;
197
- token = token.substring(1);
198
- }
199
- switch (token) {
200
- case "inf": case "INF": case "Inf":
201
- return sign * Infinity;
202
- case "nan": case "NAN": case "Nan": case "NaN":
203
- return NaN;
204
- case "0":
205
- return 0;
206
- }
207
- if (base10Re.test(token))
208
- return sign * parseInt(token, 10);
209
- if (base16Re.test(token))
210
- return sign * parseInt(token, 16);
211
- if (base8Re.test(token))
212
- return sign * parseInt(token, 8);
213
-
214
- /* istanbul ignore else */
215
- if (numberRe.test(token))
216
- return sign * parseFloat(token);
217
-
218
- /* istanbul ignore next */
219
- throw illegal(token, "number", insideTryCatch);
220
- }
221
-
222
- function parseId(token, acceptNegative, max) {
223
- switch (token) {
224
- case "max": case "MAX": case "Max":
225
- return max || maxFieldId;
226
- case "0":
227
- return 0;
228
- }
229
-
230
- /* istanbul ignore if */
231
- if (!acceptNegative && token.charAt(0) === "-")
232
- throw illegal(token, "id");
233
-
234
- if (base10NegRe.test(token))
235
- return parseInt(token, 10);
236
- if (base16NegRe.test(token))
237
- return parseInt(token, 16);
238
-
239
- /* istanbul ignore else */
240
- if (base8NegRe.test(token))
241
- return parseInt(token, 8);
242
-
243
- /* istanbul ignore next */
244
- throw illegal(token, "id");
245
- }
246
-
247
- function parsePackage() {
248
- /* istanbul ignore if */
249
- if (pkg !== undefined)
250
- throw illegal("package");
251
-
252
- pkg = next();
253
-
254
- /* istanbul ignore if */
255
- if (!typeRefRe.test(pkg))
256
- throw illegal(pkg, "name");
257
-
258
- ptr = ptr.define(pkg);
259
-
260
- skip(";");
261
- }
262
-
263
- function parseImport() {
264
- var token = peek();
265
- var whichImports;
266
- switch (token) {
267
- case "option":
268
- if (edition < "2024") {
269
- throw illegal("option");
270
- }
271
- // Import options are only used for resolving options, which we don't
272
- // do. We can just throw them out.
273
- next();
274
- readString();
275
- skip(";");
276
- return;
277
- case "weak":
278
- whichImports = weakImports || (weakImports = []);
279
- next();
280
- break;
281
- case "public":
282
- next();
283
- // eslint-disable-next-line no-fallthrough
284
- default:
285
- whichImports = imports || (imports = []);
286
- break;
287
- }
288
- token = readString();
289
- skip(";");
290
- whichImports.push(token);
291
- }
292
-
293
- function parseSyntax() {
294
- skip("=");
295
- edition = readString();
296
-
297
- /* istanbul ignore if */
298
- if (edition < 2023)
299
- throw illegal(edition, "syntax");
300
-
301
- skip(";");
302
- }
303
-
304
- function parseEdition() {
305
- skip("=");
306
- edition = readString();
307
- const supportedEditions = ["2023", "2024"];
308
-
309
- /* istanbul ignore if */
310
- if (!supportedEditions.includes(edition))
311
- throw illegal(edition, "edition");
312
-
313
- skip(";");
314
- }
315
-
316
-
317
- function parseCommon(parent, token, depth) {
318
- if (depth === undefined)
319
- depth = 0;
320
- // depth is checked by dispatched functions
321
- switch (token) {
322
-
323
- case "option":
324
- parseOption(parent, token);
325
- skip(";");
326
- return true;
327
-
328
- case "message":
329
- parseType(parent, token, depth + 1);
330
- return true;
331
-
332
- case "enum":
333
- parseEnum(parent, token);
334
- return true;
335
-
336
- case "export":
337
- case "local":
338
- if (edition < "2024") {
339
- return false;
340
- }
341
- token = next();
342
- if (token === "export" || token === "local") {
343
- return false;
344
- }
345
- if (token !== "message" && token !== "enum") {
346
- return false;
347
- }
348
- /* eslint-disable no-warning-comments */
349
- // TODO: actually enforce visiblity modifiers like protoc does.
350
- return parseCommon(parent, token, depth);
351
-
352
- case "service":
353
- parseService(parent, token, depth + 1);
354
- return true;
355
-
356
- case "extend":
357
- parseExtension(parent, token, depth);
358
- return true;
359
- }
360
- return false;
361
- }
362
-
363
- function ifBlock(obj, fnIf, fnElse) {
364
- var trailingLine = tn.line;
365
- if (obj) {
366
- if(typeof obj.comment !== "string") {
367
- obj.comment = cmnt(); // try block-type comment
368
- }
369
- obj.filename = parse.filename;
370
- }
371
- if (skip("{", true)) {
372
- var token;
373
- while ((token = next()) !== "}")
374
- fnIf(token);
375
- skip(";", true);
376
- } else {
377
- if (fnElse)
378
- fnElse();
379
- skip(";");
380
- if (obj && (typeof obj.comment !== "string" || preferTrailingComment))
381
- obj.comment = cmnt(trailingLine) || obj.comment; // try line-type comment
382
- }
383
- }
384
-
385
- function parseType(parent, token, depth) {
386
- if (depth === undefined)
387
- depth = 0;
388
- if (depth > util.nestingLimit)
389
- throw Error("max depth exceeded");
390
-
391
- /* istanbul ignore if */
392
- if (!nameRe.test(token = next()))
393
- throw illegal(token, "type name");
394
-
395
- var type = new Type(token);
396
- ifBlock(type, function parseType_block(token) {
397
- if (parseCommon(type, token, depth))
398
- return;
399
-
400
- switch (token) {
401
-
402
- case ";":
403
- break;
404
-
405
- case "map":
406
- parseMapField(type, token);
407
- break;
408
-
409
- case "required":
410
- if (edition !== "proto2")
411
- throw illegal(token);
412
- /* eslint-disable no-fallthrough */
413
- case "repeated":
414
- parseField(type, token, undefined, depth + 1);
415
- break;
416
-
417
- case "optional":
418
- /* istanbul ignore if */
419
- if (edition === "proto3") {
420
- parseField(type, "proto3_optional", undefined, depth + 1);
421
- } else if (edition !== "proto2") {
422
- throw illegal(token);
423
- } else {
424
- parseField(type, "optional", undefined, depth + 1);
425
- }
426
- break;
427
-
428
- case "oneof":
429
- parseOneOf(type, token, depth + 1);
430
- break;
431
-
432
- case "extensions":
433
- readRanges(type.extensions || (type.extensions = []));
434
- break;
435
-
436
- case "reserved":
437
- readRanges(type.reserved || (type.reserved = []), true);
438
- break;
439
-
440
- default:
441
- /* istanbul ignore if */
442
- if (edition === "proto2" || !typeRefRe.test(token)) {
443
- throw illegal(token);
444
- }
445
-
446
- push(token);
447
- parseField(type, "optional", undefined, depth + 1);
448
- break;
449
- }
450
- });
451
- parent.add(type);
452
- if (parent === ptr) {
453
- topLevelObjects.push(type);
454
- }
455
- }
456
-
457
- function parseField(parent, rule, extend, depth) {
458
- var type = next();
459
- if (type === "group") {
460
- parseGroup(parent, rule, extend, depth);
461
- return;
462
- }
463
- // Type names can consume multiple tokens, in multiple variants:
464
- // package.subpackage field tokens: "package.subpackage" [TYPE NAME ENDS HERE] "field"
465
- // package . subpackage field tokens: "package" "." "subpackage" [TYPE NAME ENDS HERE] "field"
466
- // package. subpackage field tokens: "package." "subpackage" [TYPE NAME ENDS HERE] "field"
467
- // package .subpackage field tokens: "package" ".subpackage" [TYPE NAME ENDS HERE] "field"
468
- // Keep reading tokens until we get a type name with no period at the end,
469
- // and the next token does not start with a period.
470
- while (type.endsWith(".") || peek().startsWith(".")) {
471
- type += next();
472
- }
473
-
474
- /* istanbul ignore if */
475
- if (!typeRefRe.test(type))
476
- throw illegal(type, "type");
477
-
478
- var name = next();
479
-
480
- /* istanbul ignore if */
481
-
482
- if (!nameRe.test(name))
483
- throw illegal(name, "name");
484
-
485
- var protoName = name;
486
- name = applyCase(name);
487
- skip("=");
488
-
489
- var field = new Field(name, parseId(next()), type, rule === "proto3_optional" ? "optional" : rule, extend);
490
- if (protoName !== name)
491
- field.protoName = protoName;
492
-
493
- ifBlock(field, function parseField_block(token) {
494
-
495
- /* istanbul ignore else */
496
- if (token === "option") {
497
- parseOption(field, token);
498
- skip(";");
499
- } else
500
- throw illegal(token);
501
-
502
- }, function parseField_line() {
503
- parseInlineOptions(field);
504
- });
505
-
506
- if (rule === "proto3_optional") {
507
- // for proto3 optional fields, we create a single-member Oneof to mimic "optional" behavior
508
- var oneof = new OneOf("_" + name);
509
- field.setOption("proto3_optional", true);
510
- oneof.add(field);
511
- parent.add(oneof);
512
- } else {
513
- parent.add(field);
514
- }
515
- if (parent === ptr) {
516
- topLevelObjects.push(field);
517
- }
518
- }
519
-
520
- function parseGroup(parent, rule, extend, depth) {
521
- if (depth === undefined)
522
- depth = 0;
523
- if (depth > util.nestingLimit)
524
- throw Error("max depth exceeded");
525
- if (edition >= 2023) {
526
- throw illegal("group");
527
- }
528
- var name = next();
529
-
530
- /* istanbul ignore if */
531
- if (!nameRe.test(name))
532
- throw illegal(name, "name");
533
-
534
- var fieldName = util.lcFirst(name);
535
- if (name === fieldName)
536
- name = util.ucFirst(name);
537
- skip("=");
538
- var id = parseId(next());
539
- var type = new Type(name);
540
- type.group = true;
541
- var field = new Field(fieldName, id, name, rule, extend);
542
- field.filename = parse.filename;
543
- ifBlock(type, function parseGroup_block(token) {
544
- switch (token) {
545
-
546
- case ";":
547
- break;
548
-
549
- case "option":
550
- parseOption(type, token);
551
- skip(";");
552
- break;
553
- case "required":
554
- case "repeated":
555
- parseField(type, token, undefined, depth + 1);
556
- break;
557
-
558
- case "optional":
559
- /* istanbul ignore if */
560
- if (edition === "proto3") {
561
- parseField(type, "proto3_optional", undefined, depth + 1);
562
- } else {
563
- parseField(type, "optional", undefined, depth + 1);
564
- }
565
- break;
566
-
567
- case "message":
568
- parseType(type, token, depth + 1);
569
- break;
570
-
571
- case "enum":
572
- parseEnum(type, token);
573
- break;
574
-
575
- case "reserved":
576
- readRanges(type.reserved || (type.reserved = []), true);
577
- break;
578
-
579
- case "export":
580
- case "local":
581
- if (edition < "2024") {
582
- throw illegal(token);
583
- }
584
- token = next();
585
- switch (token) {
586
- case "message":
587
- parseType(type, token, depth + 1);
588
- break;
589
- case "enum":
590
- parseType(type, token, depth + 1);
591
- break;
592
- default:
593
- throw illegal(token);
594
- }
595
- break;
596
-
597
- /* istanbul ignore next */
598
- default:
599
- throw illegal(token); // there are no groups with proto3 semantics
600
- }
601
- });
602
- parent.add(type)
603
- .add(field);
604
- if (parent === ptr) {
605
- topLevelObjects.push(type);
606
- topLevelObjects.push(field);
607
- }
608
- }
609
-
610
- function parseMapField(parent) {
611
- skip("<");
612
- var keyType = next();
613
-
614
- /* istanbul ignore if */
615
- if (types.mapKey[keyType] === undefined)
616
- throw illegal(keyType, "type");
617
-
618
- skip(",");
619
- var valueType = next();
620
-
621
- /* istanbul ignore if */
622
- if (!typeRefRe.test(valueType))
623
- throw illegal(valueType, "type");
624
-
625
- skip(">");
626
- var name = next();
627
-
628
- /* istanbul ignore if */
629
- if (!nameRe.test(name))
630
- throw illegal(name, "name");
631
-
632
- skip("=");
633
- var protoName = name;
634
- name = applyCase(name);
635
- var field = new MapField(name, parseId(next()), keyType, valueType);
636
- if (protoName !== name)
637
- field.protoName = protoName;
638
- ifBlock(field, function parseMapField_block(token) {
639
-
640
- /* istanbul ignore else */
641
- if (token === "option") {
642
- parseOption(field, token);
643
- skip(";");
644
- } else
645
- throw illegal(token);
646
-
647
- }, function parseMapField_line() {
648
- parseInlineOptions(field);
649
- });
650
- parent.add(field);
651
- }
652
-
653
- function parseOneOf(parent, token, depth) {
654
-
655
- /* istanbul ignore if */
656
- if (!nameRe.test(token = next()))
657
- throw illegal(token, "name");
658
-
659
- var oneof = new OneOf(applyCase(token));
660
- ifBlock(oneof, function parseOneOf_block(token) {
661
- if (token === "option") {
662
- parseOption(oneof, token);
663
- skip(";");
664
- } else {
665
- push(token);
666
- parseField(oneof, "optional", undefined, depth);
667
- }
668
- });
669
- parent.add(oneof);
670
- }
671
-
672
- function parseEnum(parent, token) {
673
-
674
- /* istanbul ignore if */
675
- if (!nameRe.test(token = next()))
676
- throw illegal(token, "name");
677
-
678
- var enm = new Enum(token);
679
- ifBlock(enm, function parseEnum_block(token) {
680
- switch(token) {
681
- case ";":
682
- break;
683
-
684
- case "option":
685
- parseOption(enm, token);
686
- skip(";");
687
- break;
688
-
689
- case "reserved":
690
- readRanges(enm.reserved || (enm.reserved = []), true, maxEnumId, true);
691
- if(enm.reserved === undefined) enm.reserved = [];
692
- break;
693
-
694
- default:
695
- parseEnumValue(enm, token);
696
- }
697
- });
698
- parent.add(enm);
699
- if (parent === ptr) {
700
- topLevelObjects.push(enm);
701
- }
702
- }
703
-
704
- function parseEnumValue(parent, token) {
705
-
706
- /* istanbul ignore if */
707
- if (!nameRe.test(token))
708
- throw illegal(token, "name");
709
-
710
- skip("=");
711
- var value = parseId(next(), true),
712
- dummy = {
713
- options: undefined
714
- };
715
- dummy.getOption = function(name) {
716
- return this.options[name];
717
- };
718
- dummy.setOption = function(name, value) {
719
- ReflectionObject.prototype.setOption.call(dummy, name, value);
720
- };
721
- dummy.setParsedOption = function() {
722
- return undefined;
723
- };
724
- ifBlock(dummy, function parseEnumValue_block(token) {
725
-
726
- /* istanbul ignore else */
727
- if (token === "option") {
728
- parseOption(dummy, token); // skip
729
- skip(";");
730
- } else
731
- throw illegal(token);
732
-
733
- }, function parseEnumValue_line() {
734
- parseInlineOptions(dummy); // skip
735
- });
736
- parent.add(token, value, dummy.comment, dummy.parsedOptions || dummy.options);
737
- }
738
-
739
- function parseOption(parent, token) {
740
- var option;
741
- var propName;
742
- var isOption = true;
743
- if (token === "option") {
744
- token = next();
745
- }
746
-
747
- while (token !== "=") {
748
- if (token === "(") {
749
- var parensValue = next();
750
- skip(")");
751
- token = "(" + parensValue + ")";
752
- }
753
- if (isOption) {
754
- isOption = false;
755
- if (token.includes(".") && !token.includes("(")) {
756
- var tokens = token.split(".");
757
- option = tokens[0] + ".";
758
- token = tokens[1];
759
- continue;
760
- }
761
- option = token;
762
- } else {
763
- propName = propName ? propName += token : token;
764
- }
765
- token = next();
766
- }
767
- var name = propName ? option.concat(propName) : option;
768
- var optionValue = parseOptionValue(parent, name);
769
- propName = propName && propName[0] === "." ? propName.slice(1) : propName;
770
- option = option && option[option.length - 1] === "." ? option.slice(0, -1) : option;
771
- setParsedOption(parent, option, optionValue, propName);
772
- }
773
-
774
- function parseOptionValue(parent, name, depth) {
775
- if (depth === undefined)
776
- depth = 0;
777
- if (depth > util.recursionLimit)
778
- throw Error("max depth exceeded");
779
- // { a: "foo" b { c: "bar" } }
780
- if (skip("{", true)) {
781
- var objectResult = {};
782
-
783
- while (!skip("}", true)) {
784
- /* istanbul ignore if */
785
- if (!nameRe.test(token = next())) {
786
- throw illegal(token, "name");
787
- }
788
- if (token === null) {
789
- throw illegal(token, "end of input");
790
- }
791
-
792
- var value;
793
- var propName = token;
794
-
795
- skip(":", true);
796
-
797
- if (peek() === "{") {
798
- // option (my_option) = {
799
- // repeated_value: [ "foo", "bar" ]
800
- // };
801
- value = parseOptionValue(parent, name + "." + token, depth + 1);
802
- } else if (peek() === "[") {
803
- value = [];
804
- var lastValue;
805
- if (skip("[", true)) {
806
- if (!skip("]", true)) {
807
- do {
808
- lastValue = readValue(true);
809
- value.push(lastValue);
810
- } while (skip(",", true));
811
- skip("]");
812
- if (typeof lastValue !== "undefined") {
813
- setOption(parent, name + "." + token, lastValue);
814
- }
815
- }
816
- }
817
- } else {
818
- value = readValue(true);
819
- setOption(parent, name + "." + token, value);
820
- }
821
-
822
- var prevValue = objectResult[propName];
823
-
824
- if (prevValue)
825
- value = [].concat(prevValue).concat(value);
826
-
827
- if (propName !== "__proto__")
828
- objectResult[propName] = value;
829
-
830
- // Semicolons and commas can be optional
831
- skip(",", true);
832
- skip(";", true);
833
- }
834
-
835
- return objectResult;
836
- }
837
-
838
- var simpleValue = readValue(true);
839
- setOption(parent, name, simpleValue);
840
- return simpleValue;
841
- // Does not enforce a delimiter to be universal
842
- }
843
-
844
- function setOption(parent, name, value) {
845
- if (ptr === parent && /^features\./.test(name)) {
846
- topLevelOptions[name] = value;
847
- return;
848
- }
849
- // lift json_name onto Field
850
- if (name === "json_name" && parent instanceof Field) {
851
- parent.jsonName = value;
852
- return;
853
- }
854
- if (parent.setOption)
855
- parent.setOption(name, value);
856
- }
857
-
858
- function setParsedOption(parent, name, value, propName) {
859
- if (name === "json_name" && parent instanceof Field)
860
- return; // lifted onto Field#jsonName above
861
- if (parent.setParsedOption)
862
- parent.setParsedOption(name, value, propName);
863
- }
864
-
865
- function parseInlineOptions(parent) {
866
- if (skip("[", true)) {
867
- do {
868
- parseOption(parent, "option");
869
- } while (skip(",", true));
870
- skip("]");
871
- }
872
- return parent;
873
- }
874
-
875
- function parseService(parent, token, depth) {
876
- if (depth === undefined)
877
- depth = 0;
878
- if (depth > util.recursionLimit)
879
- throw Error("max depth exceeded");
880
-
881
- /* istanbul ignore if */
882
- if (!nameRe.test(token = next()))
883
- throw illegal(token, "service name");
884
-
885
- var service = new Service(token);
886
- ifBlock(service, function parseService_block(token) {
887
- if (parseCommon(service, token, depth)) {
888
- return;
889
- }
890
-
891
- /* istanbul ignore else */
892
- if (token === ";")
893
- return;
894
- if (token === "rpc")
895
- parseMethod(service, token);
896
- else
897
- throw illegal(token);
898
- });
899
- parent.add(service);
900
- if (parent === ptr) {
901
- topLevelObjects.push(service);
902
- }
903
- }
904
-
905
- function parseMethod(parent, token) {
906
- // Get the comment of the preceding line now (if one exists) in case the
907
- // method is defined across multiple lines.
908
- var commentText = cmnt();
909
-
910
- var type = token;
911
-
912
- /* istanbul ignore if */
913
- if (!nameRe.test(token = next()))
914
- throw illegal(token, "name");
915
-
916
- var name = token,
917
- requestType, requestStream,
918
- responseType, responseStream;
919
-
920
- skip("(");
921
- if (skip("stream", true))
922
- requestStream = true;
923
-
924
- /* istanbul ignore if */
925
- if (!typeRefRe.test(token = next()))
926
- throw illegal(token);
927
-
928
- requestType = token;
929
- skip(")"); skip("returns"); skip("(");
930
- if (skip("stream", true))
931
- responseStream = true;
932
-
933
- /* istanbul ignore if */
934
- if (!typeRefRe.test(token = next()))
935
- throw illegal(token);
936
-
937
- responseType = token;
938
- skip(")");
939
-
940
- var method = new Method(name, type, requestType, responseType, requestStream, responseStream);
941
- method.comment = commentText;
942
- ifBlock(method, function parseMethod_block(token) {
943
-
944
- /* istanbul ignore else */
945
- if (token === ";")
946
- return;
947
- if (token === "option") {
948
- parseOption(method, token);
949
- skip(";");
950
- } else
951
- throw illegal(token);
952
-
953
- });
954
- parent.add(method);
955
- }
956
-
957
- function parseExtension(parent, token, depth) {
958
-
959
- /* istanbul ignore if */
960
- if (!typeRefRe.test(token = next()))
961
- throw illegal(token, "reference");
962
-
963
- var reference = token;
964
- ifBlock(null, function parseExtension_block(token) {
965
- switch (token) {
966
-
967
- case "required":
968
- case "repeated":
969
- parseField(parent, token, reference, depth + 1);
970
- break;
971
-
972
- case "optional":
973
- /* istanbul ignore if */
974
- if (edition === "proto3") {
975
- parseField(parent, "proto3_optional", reference, depth + 1);
976
- } else {
977
- parseField(parent, "optional", reference, depth + 1);
978
- }
979
- break;
980
-
981
- default:
982
- /* istanbul ignore if */
983
- if (edition === "proto2" || !typeRefRe.test(token))
984
- throw illegal(token);
985
- push(token);
986
- parseField(parent, "optional", reference, depth + 1);
987
- break;
988
- }
989
- });
990
- }
991
-
992
- var token;
993
- while ((token = next()) !== null) {
994
- switch (token) {
995
-
996
- case ";":
997
- break;
998
-
999
- case "package":
1000
-
1001
- /* istanbul ignore if */
1002
- if (!head)
1003
- throw illegal(token);
1004
-
1005
- parsePackage();
1006
- break;
1007
-
1008
- case "import":
1009
-
1010
- parseImport();
1011
- break;
1012
-
1013
- case "syntax":
1014
-
1015
- /* istanbul ignore if */
1016
- if (!head)
1017
- throw illegal(token);
1018
-
1019
- parseSyntax();
1020
- break;
1021
-
1022
- case "edition":
1023
- /* istanbul ignore if */
1024
- if (!head)
1025
- throw illegal(token);
1026
- parseEdition();
1027
- break;
1028
-
1029
- case "option":
1030
- parseOption(ptr, token);
1031
- skip(";", true);
1032
- break;
1033
-
1034
- default:
1035
-
1036
- /* istanbul ignore else */
1037
- if (parseCommon(ptr, token, 0)) {
1038
- head = false;
1039
- continue;
1040
- }
1041
-
1042
- /* istanbul ignore next */
1043
- throw illegal(token);
1044
- }
1045
- }
1046
-
1047
- resolveFileFeatures();
1048
-
1049
- parse.filename = null;
1050
- return {
1051
- "package" : pkg,
1052
- "imports" : imports,
1053
- weakImports : weakImports,
1054
- root : root
1055
- };
1056
- }
1057
-
1058
- /**
1059
- * Parses the given .proto source and returns an object with the parsed contents.
1060
- * @name parse
1061
- * @function
1062
- * @param {string} source Source contents
1063
- * @param {IParseOptions} [options] Parse options. Defaults to {@link parse.defaults} when omitted.
1064
- * @returns {IParserResult} Parser result
1065
- * @property {string} filename=null Currently processing file name for error reporting, if known
1066
- * @property {IParseOptions} defaults Default {@link IParseOptions}
1067
- * @variation 2
1068
- */
1
+ "use strict";
2
+ module.exports = parse;
3
+
4
+ parse.filename = null;
5
+ parse.defaults = { keepCase: false };
6
+
7
+ var tokenize = require("./tokenize"),
8
+ Root = require("./root"),
9
+ Type = require("./type"),
10
+ Field = require("./field"),
11
+ MapField = require("./mapfield"),
12
+ OneOf = require("./oneof"),
13
+ Enum = require("./enum"),
14
+ Service = require("./service"),
15
+ Method = require("./method"),
16
+ ReflectionObject = require("./object"),
17
+ types = require("./types"),
18
+ util = require("./util");
19
+
20
+ var base10Re = /^[1-9][0-9]*$/,
21
+ base10NegRe = /^-?[1-9][0-9]*$/,
22
+ base16Re = /^0[x][0-9a-fA-F]+$/,
23
+ base16NegRe = /^-?0[x][0-9a-fA-F]+$/,
24
+ base8Re = /^0[0-7]+$/,
25
+ base8NegRe = /^-?0[0-7]+$/,
26
+ numberRe = util.patterns.numberRe,
27
+ nameRe = /^[a-zA-Z_][a-zA-Z_0-9]*$/,
28
+ typeRefRe = util.patterns.typeRefRe;
29
+
30
+ var maxFieldId = 536870911, // 2^29 - 1
31
+ maxEnumId = 2147483647; // 2^31 - 1
32
+
33
+ /**
34
+ * Result object returned from {@link parse}.
35
+ * @interface IParserResult
36
+ * @property {string|undefined} package Package name, if declared
37
+ * @property {string[]|undefined} imports Imports, if any
38
+ * @property {string[]|undefined} weakImports Weak imports, if any
39
+ * @property {Root} root Populated root instance
40
+ */
41
+
42
+ /**
43
+ * Options modifying the behavior of {@link parse}.
44
+ * @interface IParseOptions
45
+ * @property {boolean} [keepCase=false] Keeps field casing instead of converting to camel case
46
+ * @property {boolean} [alternateCommentMode=false] Recognize double-slash comments in addition to doc-block comments.
47
+ * @property {boolean} [preferTrailingComment=false] Use trailing comment when both leading comment and trailing comment exist.
48
+ */
49
+
50
+ /**
51
+ * Options modifying the behavior of JSON serialization.
52
+ * @interface IToJSONOptions
53
+ * @property {boolean} [keepComments=false] Serializes comments.
54
+ */
55
+
56
+ /**
57
+ * Parses the given .proto source and returns an object with the parsed contents.
58
+ * @param {string} source Source contents
59
+ * @param {Root} root Root to populate
60
+ * @param {IParseOptions} [options] Parse options. Defaults to {@link parse.defaults} when omitted.
61
+ * @returns {IParserResult} Parser result
62
+ * @property {string} filename=null Currently processing file name for error reporting, if known
63
+ * @property {IParseOptions} defaults Default {@link IParseOptions}
64
+ */
65
+ function parse(source, root, options) {
66
+ /* eslint-disable callback-return */
67
+ if (!(root instanceof Root)) {
68
+ options = root;
69
+ root = new Root();
70
+ }
71
+ if (!options)
72
+ options = parse.defaults;
73
+
74
+ var preferTrailingComment = options.preferTrailingComment || false;
75
+ var tn = tokenize(source, options.alternateCommentMode || false),
76
+ next = tn.next,
77
+ push = tn.push,
78
+ peek = tn.peek,
79
+ skip = tn.skip,
80
+ cmnt = tn.cmnt;
81
+
82
+ var head = true,
83
+ pkg,
84
+ imports,
85
+ weakImports,
86
+ edition = "proto2";
87
+
88
+ var ptr = root;
89
+
90
+ var topLevelObjects = [];
91
+ var topLevelOptions = {};
92
+
93
+ var applyCase = options.keepCase ? function(name) { return name; } : util.camelCase;
94
+
95
+ function resolveFileFeatures() {
96
+ topLevelObjects.forEach(obj => {
97
+ obj._edition = edition;
98
+ Object.keys(topLevelOptions).forEach(opt => {
99
+ if (obj.getOption(opt) !== undefined) return;
100
+ obj.setOption(opt, topLevelOptions[opt], true);
101
+ });
102
+ });
103
+ }
104
+
105
+ /* istanbul ignore next */
106
+ function illegal(token, name, insideTryCatch) {
107
+ var filename = parse.filename;
108
+ if (!insideTryCatch)
109
+ parse.filename = null;
110
+ return Error("illegal " + (name || "token") + " '" + token + "' (" + (filename ? filename + ", " : "") + "line " + tn.line + ")");
111
+ }
112
+
113
+ function readString() {
114
+ var values = [],
115
+ token;
116
+ do {
117
+ /* istanbul ignore if */
118
+ if ((token = next()) !== "\"" && token !== "'")
119
+ throw illegal(token);
120
+
121
+ values.push(next());
122
+ skip(token);
123
+ token = peek();
124
+ } while (token === "\"" || token === "'");
125
+ return values.join("");
126
+ }
127
+
128
+ function readValue(acceptTypeRef) {
129
+ var token = next();
130
+ switch (token) {
131
+ case "'":
132
+ case "\"":
133
+ push(token);
134
+ return readString();
135
+ case "true": case "TRUE":
136
+ return true;
137
+ case "false": case "FALSE":
138
+ return false;
139
+ }
140
+ try {
141
+ return parseNumber(token, /* insideTryCatch */ true);
142
+ } catch (e) {
143
+ /* istanbul ignore else */
144
+ if (acceptTypeRef && typeRefRe.test(token))
145
+ return token;
146
+
147
+ /* istanbul ignore next */
148
+ throw illegal(token, "value");
149
+ }
150
+ }
151
+
152
+ function readRanges(target, acceptStrings, max, acceptNegative) {
153
+ var token, start;
154
+ do {
155
+ if (acceptStrings && ((token = peek()) === "\"" || token === "'")) {
156
+ var str = readString();
157
+ target.push(str);
158
+ if (edition >= 2023) {
159
+ throw illegal(str, "id");
160
+ }
161
+ } else {
162
+ try {
163
+ target.push([ start = parseId(next(), acceptNegative, max), skip("to", true) ? parseId(next(), acceptNegative, max) : start ]);
164
+ } catch (err) {
165
+ if (acceptStrings && typeRefRe.test(token) && edition >= 2023) {
166
+ target.push(token);
167
+ } else {
168
+ throw err;
169
+ }
170
+ }
171
+ }
172
+ } while (skip(",", true));
173
+ var dummy = {options: undefined};
174
+ dummy.setOption = function(name, value) {
175
+ if (this.options === undefined) this.options = {};
176
+ this.options[name] = value;
177
+ };
178
+ ifBlock(
179
+ dummy,
180
+ function parseRange_block(token) {
181
+ /* istanbul ignore else */
182
+ if (token === "option") {
183
+ parseOption(dummy, token); // skip
184
+ skip(";");
185
+ } else
186
+ throw illegal(token);
187
+ },
188
+ function parseRange_line() {
189
+ parseInlineOptions(dummy); // skip
190
+ });
191
+ }
192
+
193
+ function parseNumber(token, insideTryCatch) {
194
+ var sign = 1;
195
+ if (token.charAt(0) === "-") {
196
+ sign = -1;
197
+ token = token.substring(1);
198
+ }
199
+ switch (token) {
200
+ case "inf": case "INF": case "Inf":
201
+ return sign * Infinity;
202
+ case "nan": case "NAN": case "Nan": case "NaN":
203
+ return NaN;
204
+ case "0":
205
+ return 0;
206
+ }
207
+ if (base10Re.test(token))
208
+ return sign * parseInt(token, 10);
209
+ if (base16Re.test(token))
210
+ return sign * parseInt(token, 16);
211
+ if (base8Re.test(token))
212
+ return sign * parseInt(token, 8);
213
+
214
+ /* istanbul ignore else */
215
+ if (numberRe.test(token))
216
+ return sign * parseFloat(token);
217
+
218
+ /* istanbul ignore next */
219
+ throw illegal(token, "number", insideTryCatch);
220
+ }
221
+
222
+ function parseId(token, acceptNegative, max) {
223
+ switch (token) {
224
+ case "max": case "MAX": case "Max":
225
+ return max || maxFieldId;
226
+ case "0":
227
+ return 0;
228
+ }
229
+
230
+ /* istanbul ignore if */
231
+ if (!acceptNegative && token.charAt(0) === "-")
232
+ throw illegal(token, "id");
233
+
234
+ if (base10NegRe.test(token))
235
+ return parseInt(token, 10);
236
+ if (base16NegRe.test(token))
237
+ return parseInt(token, 16);
238
+
239
+ /* istanbul ignore else */
240
+ if (base8NegRe.test(token))
241
+ return parseInt(token, 8);
242
+
243
+ /* istanbul ignore next */
244
+ throw illegal(token, "id");
245
+ }
246
+
247
+ function parsePackage() {
248
+ /* istanbul ignore if */
249
+ if (pkg !== undefined)
250
+ throw illegal("package");
251
+
252
+ pkg = next();
253
+
254
+ /* istanbul ignore if */
255
+ if (!typeRefRe.test(pkg))
256
+ throw illegal(pkg, "name");
257
+
258
+ ptr = ptr.define(pkg);
259
+
260
+ skip(";");
261
+ }
262
+
263
+ function parseImport() {
264
+ var token = peek();
265
+ var whichImports;
266
+ switch (token) {
267
+ case "option":
268
+ if (edition < "2024") {
269
+ throw illegal("option");
270
+ }
271
+ // Import options are only used for resolving options, which we don't
272
+ // do. We can just throw them out.
273
+ next();
274
+ readString();
275
+ skip(";");
276
+ return;
277
+ case "weak":
278
+ whichImports = weakImports || (weakImports = []);
279
+ next();
280
+ break;
281
+ case "public":
282
+ next();
283
+ // eslint-disable-next-line no-fallthrough
284
+ default:
285
+ whichImports = imports || (imports = []);
286
+ break;
287
+ }
288
+ token = readString();
289
+ skip(";");
290
+ whichImports.push(token);
291
+ }
292
+
293
+ function parseSyntax() {
294
+ skip("=");
295
+ edition = readString();
296
+
297
+ /* istanbul ignore if */
298
+ if (edition < 2023)
299
+ throw illegal(edition, "syntax");
300
+
301
+ skip(";");
302
+ }
303
+
304
+ function parseEdition() {
305
+ skip("=");
306
+ edition = readString();
307
+ const supportedEditions = ["2023", "2024"];
308
+
309
+ /* istanbul ignore if */
310
+ if (!supportedEditions.includes(edition))
311
+ throw illegal(edition, "edition");
312
+
313
+ skip(";");
314
+ }
315
+
316
+
317
+ function parseCommon(parent, token, depth) {
318
+ if (depth === undefined)
319
+ depth = 0;
320
+ // depth is checked by dispatched functions
321
+ switch (token) {
322
+
323
+ case "option":
324
+ parseOption(parent, token);
325
+ skip(";");
326
+ return true;
327
+
328
+ case "message":
329
+ parseType(parent, token, depth + 1);
330
+ return true;
331
+
332
+ case "enum":
333
+ parseEnum(parent, token);
334
+ return true;
335
+
336
+ case "export":
337
+ case "local":
338
+ if (edition < "2024") {
339
+ return false;
340
+ }
341
+ token = next();
342
+ if (token === "export" || token === "local") {
343
+ return false;
344
+ }
345
+ if (token !== "message" && token !== "enum") {
346
+ return false;
347
+ }
348
+ /* eslint-disable no-warning-comments */
349
+ // TODO: actually enforce visiblity modifiers like protoc does.
350
+ return parseCommon(parent, token, depth);
351
+
352
+ case "service":
353
+ parseService(parent, token, depth + 1);
354
+ return true;
355
+
356
+ case "extend":
357
+ parseExtension(parent, token, depth);
358
+ return true;
359
+ }
360
+ return false;
361
+ }
362
+
363
+ function ifBlock(obj, fnIf, fnElse) {
364
+ var trailingLine = tn.line;
365
+ if (obj) {
366
+ if(typeof obj.comment !== "string") {
367
+ obj.comment = cmnt(); // try block-type comment
368
+ }
369
+ obj.filename = parse.filename;
370
+ }
371
+ if (skip("{", true)) {
372
+ var token;
373
+ while ((token = next()) !== "}")
374
+ fnIf(token);
375
+ skip(";", true);
376
+ } else {
377
+ if (fnElse)
378
+ fnElse();
379
+ skip(";");
380
+ if (obj && (typeof obj.comment !== "string" || preferTrailingComment))
381
+ obj.comment = cmnt(trailingLine) || obj.comment; // try line-type comment
382
+ }
383
+ }
384
+
385
+ function parseType(parent, token, depth) {
386
+ if (depth === undefined)
387
+ depth = 0;
388
+ if (depth > util.nestingLimit)
389
+ throw Error("max depth exceeded");
390
+
391
+ /* istanbul ignore if */
392
+ if (!nameRe.test(token = next()))
393
+ throw illegal(token, "type name");
394
+
395
+ var type = new Type(token);
396
+ ifBlock(type, function parseType_block(token) {
397
+ if (parseCommon(type, token, depth))
398
+ return;
399
+
400
+ switch (token) {
401
+
402
+ case ";":
403
+ break;
404
+
405
+ case "map":
406
+ parseMapField(type, token);
407
+ break;
408
+
409
+ case "required":
410
+ if (edition !== "proto2")
411
+ throw illegal(token);
412
+ /* eslint-disable no-fallthrough */
413
+ case "repeated":
414
+ parseField(type, token, undefined, depth + 1);
415
+ break;
416
+
417
+ case "optional":
418
+ /* istanbul ignore if */
419
+ if (edition === "proto3") {
420
+ parseField(type, "proto3_optional", undefined, depth + 1);
421
+ } else if (edition !== "proto2") {
422
+ throw illegal(token);
423
+ } else {
424
+ parseField(type, "optional", undefined, depth + 1);
425
+ }
426
+ break;
427
+
428
+ case "oneof":
429
+ parseOneOf(type, token, depth + 1);
430
+ break;
431
+
432
+ case "extensions":
433
+ readRanges(type.extensions || (type.extensions = []));
434
+ break;
435
+
436
+ case "reserved":
437
+ readRanges(type.reserved || (type.reserved = []), true);
438
+ break;
439
+
440
+ default:
441
+ /* istanbul ignore if */
442
+ if (edition === "proto2" || !typeRefRe.test(token)) {
443
+ throw illegal(token);
444
+ }
445
+
446
+ push(token);
447
+ parseField(type, "optional", undefined, depth + 1);
448
+ break;
449
+ }
450
+ });
451
+ parent.add(type);
452
+ if (parent === ptr) {
453
+ topLevelObjects.push(type);
454
+ }
455
+ }
456
+
457
+ function parseField(parent, rule, extend, depth) {
458
+ var type = next();
459
+ if (type === "group") {
460
+ parseGroup(parent, rule, extend, depth);
461
+ return;
462
+ }
463
+ // Type names can consume multiple tokens, in multiple variants:
464
+ // package.subpackage field tokens: "package.subpackage" [TYPE NAME ENDS HERE] "field"
465
+ // package . subpackage field tokens: "package" "." "subpackage" [TYPE NAME ENDS HERE] "field"
466
+ // package. subpackage field tokens: "package." "subpackage" [TYPE NAME ENDS HERE] "field"
467
+ // package .subpackage field tokens: "package" ".subpackage" [TYPE NAME ENDS HERE] "field"
468
+ // Keep reading tokens until we get a type name with no period at the end,
469
+ // and the next token does not start with a period.
470
+ while (type.endsWith(".") || peek().startsWith(".")) {
471
+ type += next();
472
+ }
473
+
474
+ /* istanbul ignore if */
475
+ if (!typeRefRe.test(type))
476
+ throw illegal(type, "type");
477
+
478
+ var name = next();
479
+
480
+ /* istanbul ignore if */
481
+
482
+ if (!nameRe.test(name))
483
+ throw illegal(name, "name");
484
+
485
+ var protoName = name;
486
+ name = applyCase(name);
487
+ skip("=");
488
+
489
+ var field = new Field(name, parseId(next()), type, rule === "proto3_optional" ? "optional" : rule, extend);
490
+ if (protoName !== name)
491
+ field.protoName = protoName;
492
+
493
+ ifBlock(field, function parseField_block(token) {
494
+
495
+ /* istanbul ignore else */
496
+ if (token === "option") {
497
+ parseOption(field, token);
498
+ skip(";");
499
+ } else
500
+ throw illegal(token);
501
+
502
+ }, function parseField_line() {
503
+ parseInlineOptions(field);
504
+ });
505
+
506
+ if (rule === "proto3_optional") {
507
+ // for proto3 optional fields, we create a single-member Oneof to mimic "optional" behavior
508
+ var oneof = new OneOf("_" + name);
509
+ field.setOption("proto3_optional", true);
510
+ oneof.add(field);
511
+ parent.add(oneof);
512
+ } else {
513
+ parent.add(field);
514
+ }
515
+ if (parent === ptr) {
516
+ topLevelObjects.push(field);
517
+ }
518
+ }
519
+
520
+ function parseGroup(parent, rule, extend, depth) {
521
+ if (depth === undefined)
522
+ depth = 0;
523
+ if (depth > util.nestingLimit)
524
+ throw Error("max depth exceeded");
525
+ if (edition >= 2023) {
526
+ throw illegal("group");
527
+ }
528
+ var name = next();
529
+
530
+ /* istanbul ignore if */
531
+ if (!nameRe.test(name))
532
+ throw illegal(name, "name");
533
+
534
+ var fieldName = util.lcFirst(name);
535
+ if (name === fieldName)
536
+ name = util.ucFirst(name);
537
+ skip("=");
538
+ var id = parseId(next());
539
+ var type = new Type(name);
540
+ type.group = true;
541
+ var field = new Field(fieldName, id, name, rule, extend);
542
+ field.filename = parse.filename;
543
+ ifBlock(type, function parseGroup_block(token) {
544
+ switch (token) {
545
+
546
+ case ";":
547
+ break;
548
+
549
+ case "option":
550
+ parseOption(type, token);
551
+ skip(";");
552
+ break;
553
+ case "required":
554
+ case "repeated":
555
+ parseField(type, token, undefined, depth + 1);
556
+ break;
557
+
558
+ case "optional":
559
+ /* istanbul ignore if */
560
+ if (edition === "proto3") {
561
+ parseField(type, "proto3_optional", undefined, depth + 1);
562
+ } else {
563
+ parseField(type, "optional", undefined, depth + 1);
564
+ }
565
+ break;
566
+
567
+ case "message":
568
+ parseType(type, token, depth + 1);
569
+ break;
570
+
571
+ case "enum":
572
+ parseEnum(type, token);
573
+ break;
574
+
575
+ case "reserved":
576
+ readRanges(type.reserved || (type.reserved = []), true);
577
+ break;
578
+
579
+ case "export":
580
+ case "local":
581
+ if (edition < "2024") {
582
+ throw illegal(token);
583
+ }
584
+ token = next();
585
+ switch (token) {
586
+ case "message":
587
+ parseType(type, token, depth + 1);
588
+ break;
589
+ case "enum":
590
+ parseType(type, token, depth + 1);
591
+ break;
592
+ default:
593
+ throw illegal(token);
594
+ }
595
+ break;
596
+
597
+ /* istanbul ignore next */
598
+ default:
599
+ throw illegal(token); // there are no groups with proto3 semantics
600
+ }
601
+ });
602
+ parent.add(type)
603
+ .add(field);
604
+ if (parent === ptr) {
605
+ topLevelObjects.push(type);
606
+ topLevelObjects.push(field);
607
+ }
608
+ }
609
+
610
+ function parseMapField(parent) {
611
+ skip("<");
612
+ var keyType = next();
613
+
614
+ /* istanbul ignore if */
615
+ if (types.mapKey[keyType] === undefined)
616
+ throw illegal(keyType, "type");
617
+
618
+ skip(",");
619
+ var valueType = next();
620
+
621
+ /* istanbul ignore if */
622
+ if (!typeRefRe.test(valueType))
623
+ throw illegal(valueType, "type");
624
+
625
+ skip(">");
626
+ var name = next();
627
+
628
+ /* istanbul ignore if */
629
+ if (!nameRe.test(name))
630
+ throw illegal(name, "name");
631
+
632
+ skip("=");
633
+ var protoName = name;
634
+ name = applyCase(name);
635
+ var field = new MapField(name, parseId(next()), keyType, valueType);
636
+ if (protoName !== name)
637
+ field.protoName = protoName;
638
+ ifBlock(field, function parseMapField_block(token) {
639
+
640
+ /* istanbul ignore else */
641
+ if (token === "option") {
642
+ parseOption(field, token);
643
+ skip(";");
644
+ } else
645
+ throw illegal(token);
646
+
647
+ }, function parseMapField_line() {
648
+ parseInlineOptions(field);
649
+ });
650
+ parent.add(field);
651
+ }
652
+
653
+ function parseOneOf(parent, token, depth) {
654
+
655
+ /* istanbul ignore if */
656
+ if (!nameRe.test(token = next()))
657
+ throw illegal(token, "name");
658
+
659
+ var oneof = new OneOf(applyCase(token));
660
+ ifBlock(oneof, function parseOneOf_block(token) {
661
+ if (token === "option") {
662
+ parseOption(oneof, token);
663
+ skip(";");
664
+ } else {
665
+ push(token);
666
+ parseField(oneof, "optional", undefined, depth);
667
+ }
668
+ });
669
+ parent.add(oneof);
670
+ }
671
+
672
+ function parseEnum(parent, token) {
673
+
674
+ /* istanbul ignore if */
675
+ if (!nameRe.test(token = next()))
676
+ throw illegal(token, "name");
677
+
678
+ var enm = new Enum(token);
679
+ ifBlock(enm, function parseEnum_block(token) {
680
+ switch(token) {
681
+ case ";":
682
+ break;
683
+
684
+ case "option":
685
+ parseOption(enm, token);
686
+ skip(";");
687
+ break;
688
+
689
+ case "reserved":
690
+ readRanges(enm.reserved || (enm.reserved = []), true, maxEnumId, true);
691
+ if(enm.reserved === undefined) enm.reserved = [];
692
+ break;
693
+
694
+ default:
695
+ parseEnumValue(enm, token);
696
+ }
697
+ });
698
+ parent.add(enm);
699
+ if (parent === ptr) {
700
+ topLevelObjects.push(enm);
701
+ }
702
+ }
703
+
704
+ function parseEnumValue(parent, token) {
705
+
706
+ /* istanbul ignore if */
707
+ if (!nameRe.test(token))
708
+ throw illegal(token, "name");
709
+
710
+ skip("=");
711
+ var value = parseId(next(), true),
712
+ dummy = {
713
+ options: undefined
714
+ };
715
+ dummy.getOption = function(name) {
716
+ return this.options[name];
717
+ };
718
+ dummy.setOption = function(name, value) {
719
+ ReflectionObject.prototype.setOption.call(dummy, name, value);
720
+ };
721
+ dummy.setParsedOption = function() {
722
+ return undefined;
723
+ };
724
+ ifBlock(dummy, function parseEnumValue_block(token) {
725
+
726
+ /* istanbul ignore else */
727
+ if (token === "option") {
728
+ parseOption(dummy, token); // skip
729
+ skip(";");
730
+ } else
731
+ throw illegal(token);
732
+
733
+ }, function parseEnumValue_line() {
734
+ parseInlineOptions(dummy); // skip
735
+ });
736
+ parent.add(token, value, dummy.comment, dummy.parsedOptions || dummy.options);
737
+ }
738
+
739
+ function parseOption(parent, token) {
740
+ var option;
741
+ var propName;
742
+ var isOption = true;
743
+ if (token === "option") {
744
+ token = next();
745
+ }
746
+
747
+ while (token !== "=") {
748
+ if (token === "(") {
749
+ var parensValue = next();
750
+ skip(")");
751
+ token = "(" + parensValue + ")";
752
+ }
753
+ if (isOption) {
754
+ isOption = false;
755
+ if (token.includes(".") && !token.includes("(")) {
756
+ var tokens = token.split(".");
757
+ option = tokens[0] + ".";
758
+ token = tokens[1];
759
+ continue;
760
+ }
761
+ option = token;
762
+ } else {
763
+ propName = propName ? propName += token : token;
764
+ }
765
+ token = next();
766
+ }
767
+ var name = propName ? option.concat(propName) : option;
768
+ var optionValue = parseOptionValue(parent, name);
769
+ propName = propName && propName[0] === "." ? propName.slice(1) : propName;
770
+ option = option && option[option.length - 1] === "." ? option.slice(0, -1) : option;
771
+ setParsedOption(parent, option, optionValue, propName);
772
+ }
773
+
774
+ function parseOptionValue(parent, name, depth) {
775
+ if (depth === undefined)
776
+ depth = 0;
777
+ if (depth > util.recursionLimit)
778
+ throw Error("max depth exceeded");
779
+ // { a: "foo" b { c: "bar" } }
780
+ if (skip("{", true)) {
781
+ var objectResult = {};
782
+
783
+ while (!skip("}", true)) {
784
+ /* istanbul ignore if */
785
+ if (!nameRe.test(token = next())) {
786
+ throw illegal(token, "name");
787
+ }
788
+ if (token === null) {
789
+ throw illegal(token, "end of input");
790
+ }
791
+
792
+ var value;
793
+ var propName = token;
794
+
795
+ skip(":", true);
796
+
797
+ if (peek() === "{") {
798
+ // option (my_option) = {
799
+ // repeated_value: [ "foo", "bar" ]
800
+ // };
801
+ value = parseOptionValue(parent, name + "." + token, depth + 1);
802
+ } else if (peek() === "[") {
803
+ value = [];
804
+ var lastValue;
805
+ if (skip("[", true)) {
806
+ if (!skip("]", true)) {
807
+ do {
808
+ lastValue = readValue(true);
809
+ value.push(lastValue);
810
+ } while (skip(",", true));
811
+ skip("]");
812
+ if (typeof lastValue !== "undefined") {
813
+ setOption(parent, name + "." + token, lastValue);
814
+ }
815
+ }
816
+ }
817
+ } else {
818
+ value = readValue(true);
819
+ setOption(parent, name + "." + token, value);
820
+ }
821
+
822
+ var prevValue = objectResult[propName];
823
+
824
+ if (prevValue)
825
+ value = [].concat(prevValue).concat(value);
826
+
827
+ if (propName !== "__proto__")
828
+ objectResult[propName] = value;
829
+
830
+ // Semicolons and commas can be optional
831
+ skip(",", true);
832
+ skip(";", true);
833
+ }
834
+
835
+ return objectResult;
836
+ }
837
+
838
+ var simpleValue = readValue(true);
839
+ setOption(parent, name, simpleValue);
840
+ return simpleValue;
841
+ // Does not enforce a delimiter to be universal
842
+ }
843
+
844
+ function setOption(parent, name, value) {
845
+ if (ptr === parent && /^features\./.test(name)) {
846
+ topLevelOptions[name] = value;
847
+ return;
848
+ }
849
+ // lift json_name onto Field
850
+ if (name === "json_name" && parent instanceof Field) {
851
+ parent.jsonName = value;
852
+ return;
853
+ }
854
+ if (parent.setOption)
855
+ parent.setOption(name, value);
856
+ }
857
+
858
+ function setParsedOption(parent, name, value, propName) {
859
+ if (name === "json_name" && parent instanceof Field)
860
+ return; // lifted onto Field#jsonName above
861
+ if (parent.setParsedOption)
862
+ parent.setParsedOption(name, value, propName);
863
+ }
864
+
865
+ function parseInlineOptions(parent) {
866
+ if (skip("[", true)) {
867
+ do {
868
+ parseOption(parent, "option");
869
+ } while (skip(",", true));
870
+ skip("]");
871
+ }
872
+ return parent;
873
+ }
874
+
875
+ function parseService(parent, token, depth) {
876
+ if (depth === undefined)
877
+ depth = 0;
878
+ if (depth > util.recursionLimit)
879
+ throw Error("max depth exceeded");
880
+
881
+ /* istanbul ignore if */
882
+ if (!nameRe.test(token = next()))
883
+ throw illegal(token, "service name");
884
+
885
+ var service = new Service(token);
886
+ ifBlock(service, function parseService_block(token) {
887
+ if (parseCommon(service, token, depth)) {
888
+ return;
889
+ }
890
+
891
+ /* istanbul ignore else */
892
+ if (token === ";")
893
+ return;
894
+ if (token === "rpc")
895
+ parseMethod(service, token);
896
+ else
897
+ throw illegal(token);
898
+ });
899
+ parent.add(service);
900
+ if (parent === ptr) {
901
+ topLevelObjects.push(service);
902
+ }
903
+ }
904
+
905
+ function parseMethod(parent, token) {
906
+ // Get the comment of the preceding line now (if one exists) in case the
907
+ // method is defined across multiple lines.
908
+ var commentText = cmnt();
909
+
910
+ var type = token;
911
+
912
+ /* istanbul ignore if */
913
+ if (!nameRe.test(token = next()))
914
+ throw illegal(token, "name");
915
+
916
+ var name = token,
917
+ requestType, requestStream,
918
+ responseType, responseStream;
919
+
920
+ skip("(");
921
+ if (skip("stream", true))
922
+ requestStream = true;
923
+
924
+ /* istanbul ignore if */
925
+ if (!typeRefRe.test(token = next()))
926
+ throw illegal(token);
927
+
928
+ requestType = token;
929
+ skip(")"); skip("returns"); skip("(");
930
+ if (skip("stream", true))
931
+ responseStream = true;
932
+
933
+ /* istanbul ignore if */
934
+ if (!typeRefRe.test(token = next()))
935
+ throw illegal(token);
936
+
937
+ responseType = token;
938
+ skip(")");
939
+
940
+ var method = new Method(name, type, requestType, responseType, requestStream, responseStream);
941
+ method.comment = commentText;
942
+ ifBlock(method, function parseMethod_block(token) {
943
+
944
+ /* istanbul ignore else */
945
+ if (token === ";")
946
+ return;
947
+ if (token === "option") {
948
+ parseOption(method, token);
949
+ skip(";");
950
+ } else
951
+ throw illegal(token);
952
+
953
+ });
954
+ parent.add(method);
955
+ }
956
+
957
+ function parseExtension(parent, token, depth) {
958
+
959
+ /* istanbul ignore if */
960
+ if (!typeRefRe.test(token = next()))
961
+ throw illegal(token, "reference");
962
+
963
+ var reference = token;
964
+ ifBlock(null, function parseExtension_block(token) {
965
+ switch (token) {
966
+
967
+ case "required":
968
+ case "repeated":
969
+ parseField(parent, token, reference, depth + 1);
970
+ break;
971
+
972
+ case "optional":
973
+ /* istanbul ignore if */
974
+ if (edition === "proto3") {
975
+ parseField(parent, "proto3_optional", reference, depth + 1);
976
+ } else {
977
+ parseField(parent, "optional", reference, depth + 1);
978
+ }
979
+ break;
980
+
981
+ default:
982
+ /* istanbul ignore if */
983
+ if (edition === "proto2" || !typeRefRe.test(token))
984
+ throw illegal(token);
985
+ push(token);
986
+ parseField(parent, "optional", reference, depth + 1);
987
+ break;
988
+ }
989
+ });
990
+ }
991
+
992
+ var token;
993
+ while ((token = next()) !== null) {
994
+ switch (token) {
995
+
996
+ case ";":
997
+ break;
998
+
999
+ case "package":
1000
+
1001
+ /* istanbul ignore if */
1002
+ if (!head)
1003
+ throw illegal(token);
1004
+
1005
+ parsePackage();
1006
+ break;
1007
+
1008
+ case "import":
1009
+
1010
+ parseImport();
1011
+ break;
1012
+
1013
+ case "syntax":
1014
+
1015
+ /* istanbul ignore if */
1016
+ if (!head)
1017
+ throw illegal(token);
1018
+
1019
+ parseSyntax();
1020
+ break;
1021
+
1022
+ case "edition":
1023
+ /* istanbul ignore if */
1024
+ if (!head)
1025
+ throw illegal(token);
1026
+ parseEdition();
1027
+ break;
1028
+
1029
+ case "option":
1030
+ parseOption(ptr, token);
1031
+ skip(";", true);
1032
+ break;
1033
+
1034
+ default:
1035
+
1036
+ /* istanbul ignore else */
1037
+ if (parseCommon(ptr, token, 0)) {
1038
+ head = false;
1039
+ continue;
1040
+ }
1041
+
1042
+ /* istanbul ignore next */
1043
+ throw illegal(token);
1044
+ }
1045
+ }
1046
+
1047
+ resolveFileFeatures();
1048
+
1049
+ parse.filename = null;
1050
+ return {
1051
+ "package" : pkg,
1052
+ "imports" : imports,
1053
+ weakImports : weakImports,
1054
+ root : root
1055
+ };
1056
+ }
1057
+
1058
+ /**
1059
+ * Parses the given .proto source and returns an object with the parsed contents.
1060
+ * @name parse
1061
+ * @function
1062
+ * @param {string} source Source contents
1063
+ * @param {IParseOptions} [options] Parse options. Defaults to {@link parse.defaults} when omitted.
1064
+ * @returns {IParserResult} Parser result
1065
+ * @property {string} filename=null Currently processing file name for error reporting, if known
1066
+ * @property {IParseOptions} defaults Default {@link IParseOptions}
1067
+ * @variation 2
1068
+ */