protobufjs 3.6.0 → 3.8.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 (99) hide show
  1. package/bin/proto2js +16 -4
  2. package/bower.json +1 -1
  3. package/dist/ProtoBuf.js +645 -441
  4. package/dist/ProtoBuf.min.js +96 -96
  5. package/dist/ProtoBuf.min.js.gz +0 -0
  6. package/dist/ProtoBuf.min.map +2 -2
  7. package/dist/ProtoBuf.noparse.js +520 -357
  8. package/dist/ProtoBuf.noparse.min.js +68 -66
  9. package/dist/ProtoBuf.noparse.min.js.gz +0 -0
  10. package/dist/ProtoBuf.noparse.min.map +3 -3
  11. package/docs/ProtoBuf.Builder.Message.html +673 -135
  12. package/docs/ProtoBuf.Builder.Service.html +58 -19
  13. package/docs/ProtoBuf.Builder.html +374 -46
  14. package/docs/ProtoBuf.DotProto.Parser.html +58 -19
  15. package/docs/ProtoBuf.DotProto.Tokenizer.html +104 -19
  16. package/docs/ProtoBuf.DotProto.html +16 -10
  17. package/docs/ProtoBuf.Reflect.Enum.Value.html +207 -33
  18. package/docs/ProtoBuf.Reflect.Enum.html +318 -56
  19. package/docs/ProtoBuf.Reflect.Extension.html +53 -13
  20. package/docs/ProtoBuf.Reflect.Message.ExtensionField.html +450 -68
  21. package/docs/ProtoBuf.Reflect.Message.Field.html +454 -51
  22. package/docs/ProtoBuf.Reflect.Message.OneOf.html +1044 -0
  23. package/docs/ProtoBuf.Reflect.Message.html +378 -64
  24. package/docs/ProtoBuf.Reflect.Namespace.html +333 -51
  25. package/docs/ProtoBuf.Reflect.Service.Method.html +228 -35
  26. package/docs/ProtoBuf.Reflect.Service.RPCMethod.html +262 -41
  27. package/docs/ProtoBuf.Reflect.Service.html +318 -56
  28. package/docs/ProtoBuf.Reflect.T.html +210 -25
  29. package/docs/ProtoBuf.Reflect.html +17 -11
  30. package/docs/ProtoBuf.Util.html +59 -13
  31. package/docs/ProtoBuf.html +235 -67
  32. package/docs/ProtoBuf.js.html +648 -443
  33. package/docs/index.html +4 -2
  34. package/docs/styles/jsdoc-default.css +2 -2
  35. package/examples/protoify/.npmignore +2 -0
  36. package/examples/protoify/README.md +28 -0
  37. package/examples/protoify/index.js +147 -0
  38. package/examples/protoify/json.js +123 -0
  39. package/examples/protoify/json.json +123 -0
  40. package/examples/protoify/json.proto +30 -0
  41. package/examples/protoify/package.json +15 -0
  42. package/examples/protoify/test.js +56 -0
  43. package/examples/websocket/README.md +1 -0
  44. package/examples/websocket/package.json +1 -1
  45. package/externs/ProtoBuf.js +922 -922
  46. package/package.json +3 -3
  47. package/scripts/build.js +58 -58
  48. package/src/ProtoBuf/Builder/Message.js +107 -77
  49. package/src/ProtoBuf/Builder/Service.js +8 -5
  50. package/src/ProtoBuf/Builder.js +71 -37
  51. package/src/ProtoBuf/DotProto/Parser.js +108 -72
  52. package/src/ProtoBuf/DotProto/Tokenizer.js +17 -11
  53. package/src/ProtoBuf/Lang.js +1 -1
  54. package/src/ProtoBuf/Reflect/Enum/Value.js +3 -2
  55. package/src/ProtoBuf/Reflect/Enum.js +9 -5
  56. package/src/ProtoBuf/Reflect/Extension.js +4 -3
  57. package/src/ProtoBuf/Reflect/Message/ExtensionField.js +4 -3
  58. package/src/ProtoBuf/Reflect/Message/Field.js +45 -26
  59. package/src/ProtoBuf/Reflect/Message/OneOf.js +19 -0
  60. package/src/ProtoBuf/Reflect/Message.js +36 -19
  61. package/src/ProtoBuf/Reflect/Namespace.js +19 -15
  62. package/src/ProtoBuf/Reflect/Service/Method.js +9 -5
  63. package/src/ProtoBuf/Reflect/Service/RPCMethod.js +3 -2
  64. package/src/ProtoBuf/Reflect/Service.js +9 -5
  65. package/src/ProtoBuf/Reflect/T.js +20 -6
  66. package/src/ProtoBuf/Reflect.js +9 -0
  67. package/src/ProtoBuf/Util.js +132 -132
  68. package/src/ProtoBuf.js +15 -17
  69. package/src/google/protobuf/descriptor.json +33 -13
  70. package/tests/bench.txt +373 -373
  71. package/tests/complex.json +8 -4
  72. package/tests/custom-options.json +169 -169
  73. package/tests/extend.json +71 -71
  74. package/tests/nodeunit-browser/nodeunit.css +70 -70
  75. package/tests/nodeunit-browser/nodeunit.js +2108 -2108
  76. package/tests/oneof.proto +6 -0
  77. package/tests/options.json +32 -32
  78. package/tests/options.proto +2 -0
  79. package/tests/proto2js/Bar.json +46 -46
  80. package/tests/suite.js +83 -12
  81. package/.idea/.name +0 -1
  82. package/.idea/ProtoBuf.iml +0 -9
  83. package/.idea/dictionaries/Daniel.xml +0 -7
  84. package/.idea/encodings.xml +0 -5
  85. package/.idea/misc.xml +0 -5
  86. package/.idea/modules.xml +0 -9
  87. package/.idea/scopes/scope_settings.xml +0 -5
  88. package/.idea/vcs.xml +0 -7
  89. package/.idea/workspace.xml +0 -551
  90. package/NOTICE +0 -2
  91. package/sandbox/issue146/MyOptions.proto +0 -28
  92. package/sandbox/issue146/Sample.proto +0 -21
  93. package/sandbox/issue146/main.js +0 -3
  94. package/sandbox/issue147/enum.proto +0 -8
  95. package/sandbox/issue147/main.js +0 -3
  96. package/sandbox/issue42/innerextend.proto +0 -18
  97. package/sandbox/issue42/main.js +0 -8
  98. package/sandbox/issue42/outerextend.proto +0 -17
  99. package/v8.log +0 -3828
package/dist/ProtoBuf.js CHANGED
@@ -38,7 +38,7 @@
38
38
  * @const
39
39
  * @expose
40
40
  */
41
- ProtoBuf.VERSION = "3.6.0";
41
+ ProtoBuf.VERSION = "3.8.2";
42
42
 
43
43
  /**
44
44
  * Wire types.
@@ -234,138 +234,138 @@
234
234
  */
235
235
  ProtoBuf.populateAccessors = true;
236
236
 
237
- /**
238
- * @alias ProtoBuf.Util
239
- * @expose
240
- */
241
- ProtoBuf.Util = (function() {
242
- "use strict";
243
-
244
- // Object.create polyfill
245
- // ref: https://developer.mozilla.org/de/docs/JavaScript/Reference/Global_Objects/Object/create
246
- if (!Object.create)
247
- /** @expose */
248
- Object.create = function (o) {
249
- if (arguments.length > 1)
250
- throw Error('Object.create polyfill only accepts the first parameter.');
251
- function F() {}
252
- F.prototype = o;
253
- return new F();
254
- };
255
-
256
- /**
257
- * ProtoBuf utilities.
258
- * @exports ProtoBuf.Util
259
- * @namespace
260
- */
261
- var Util = {};
262
-
263
- /**
264
- * Flag if running in node (fs is available) or not.
265
- * @type {boolean}
266
- * @const
267
- * @expose
268
- */
269
- Util.IS_NODE = false;
270
- try {
271
- // There is no reliable way to detect node.js as an environment, so our
272
- // best bet is to feature-detect what we actually need.
273
- Util.IS_NODE =
274
- typeof require === 'function' &&
275
- typeof require("fs").readFileSync === 'function' &&
276
- typeof require("path").resolve === 'function';
277
- } catch (e) {}
278
-
279
- /**
280
- * Constructs a XMLHttpRequest object.
281
- * @return {XMLHttpRequest}
282
- * @throws {Error} If XMLHttpRequest is not supported
283
- * @expose
284
- */
285
- Util.XHR = function() {
286
- // No dependencies please, ref: http://www.quirksmode.org/js/xmlhttp.html
287
- var XMLHttpFactories = [
288
- function () {return new XMLHttpRequest()},
289
- function () {return new ActiveXObject("Msxml2.XMLHTTP")},
290
- function () {return new ActiveXObject("Msxml3.XMLHTTP")},
291
- function () {return new ActiveXObject("Microsoft.XMLHTTP")}
292
- ];
293
- /** @type {?XMLHttpRequest} */
294
- var xhr = null;
295
- for (var i=0;i<XMLHttpFactories.length;i++) {
296
- try { xhr = XMLHttpFactories[i](); }
297
- catch (e) { continue; }
298
- break;
299
- }
300
- if (!xhr)
301
- throw Error("XMLHttpRequest is not supported");
302
- return xhr;
303
- };
304
-
305
- /**
306
- * Fetches a resource.
307
- * @param {string} path Resource path
308
- * @param {function(?string)=} callback Callback receiving the resource's contents. If omitted the resource will
309
- * be fetched synchronously. If the request failed, contents will be null.
310
- * @return {?string|undefined} Resource contents if callback is omitted (null if the request failed), else undefined.
311
- * @expose
312
- */
313
- Util.fetch = function(path, callback) {
314
- if (callback && typeof callback != 'function')
315
- callback = null;
316
- if (Util.IS_NODE) {
317
- if (callback) {
318
- require("fs").readFile(path, function(err, data) {
319
- if (err)
320
- callback(null);
321
- else
322
- callback(""+data);
323
- });
324
- } else
325
- try {
326
- return require("fs").readFileSync(path);
327
- } catch (e) {
328
- return null;
329
- }
330
- } else {
331
- var xhr = Util.XHR();
332
- xhr.open('GET', path, callback ? true : false);
333
- // xhr.setRequestHeader('User-Agent', 'XMLHTTP/1.0');
334
- xhr.setRequestHeader('Accept', 'text/plain');
335
- if (typeof xhr.overrideMimeType === 'function') xhr.overrideMimeType('text/plain');
336
- if (callback) {
337
- xhr.onreadystatechange = function() {
338
- if (xhr.readyState != 4) return;
339
- if (/* remote */ xhr.status == 200 || /* local */ (xhr.status == 0 && typeof xhr.responseText === 'string'))
340
- callback(xhr.responseText);
341
- else
342
- callback(null);
343
- };
344
- if (xhr.readyState == 4)
345
- return;
346
- xhr.send(null);
347
- } else {
348
- xhr.send(null);
349
- if (/* remote */ xhr.status == 200 || /* local */ (xhr.status == 0 && typeof xhr.responseText === 'string'))
350
- return xhr.responseText;
351
- return null;
352
- }
353
- }
354
- };
355
-
356
- /**
357
- * Tests if an object is an array.
358
- * @function
359
- * @param {*} obj Object to test
360
- * @returns {boolean} true if it is an array, else false
361
- * @expose
362
- */
363
- Util.isArray = Array.isArray || function(obj) {
364
- return Object.prototype.toString.call(obj) === "[object Array]";
365
- };
366
-
367
- return Util;
368
- })();
237
+ /**
238
+ * @alias ProtoBuf.Util
239
+ * @expose
240
+ */
241
+ ProtoBuf.Util = (function() {
242
+ "use strict";
243
+
244
+ // Object.create polyfill
245
+ // ref: https://developer.mozilla.org/de/docs/JavaScript/Reference/Global_Objects/Object/create
246
+ if (!Object.create)
247
+ /** @expose */
248
+ Object.create = function (o) {
249
+ if (arguments.length > 1)
250
+ throw Error('Object.create polyfill only accepts the first parameter.');
251
+ function F() {}
252
+ F.prototype = o;
253
+ return new F();
254
+ };
255
+
256
+ /**
257
+ * ProtoBuf utilities.
258
+ * @exports ProtoBuf.Util
259
+ * @namespace
260
+ */
261
+ var Util = {};
262
+
263
+ /**
264
+ * Flag if running in node (fs is available) or not.
265
+ * @type {boolean}
266
+ * @const
267
+ * @expose
268
+ */
269
+ Util.IS_NODE = false;
270
+ try {
271
+ // There is no reliable way to detect node.js as an environment, so our
272
+ // best bet is to feature-detect what we actually need.
273
+ Util.IS_NODE =
274
+ typeof require === 'function' &&
275
+ typeof require("fs").readFileSync === 'function' &&
276
+ typeof require("path").resolve === 'function';
277
+ } catch (e) {}
278
+
279
+ /**
280
+ * Constructs a XMLHttpRequest object.
281
+ * @return {XMLHttpRequest}
282
+ * @throws {Error} If XMLHttpRequest is not supported
283
+ * @expose
284
+ */
285
+ Util.XHR = function() {
286
+ // No dependencies please, ref: http://www.quirksmode.org/js/xmlhttp.html
287
+ var XMLHttpFactories = [
288
+ function () {return new XMLHttpRequest()},
289
+ function () {return new ActiveXObject("Msxml2.XMLHTTP")},
290
+ function () {return new ActiveXObject("Msxml3.XMLHTTP")},
291
+ function () {return new ActiveXObject("Microsoft.XMLHTTP")}
292
+ ];
293
+ /** @type {?XMLHttpRequest} */
294
+ var xhr = null;
295
+ for (var i=0;i<XMLHttpFactories.length;i++) {
296
+ try { xhr = XMLHttpFactories[i](); }
297
+ catch (e) { continue; }
298
+ break;
299
+ }
300
+ if (!xhr)
301
+ throw Error("XMLHttpRequest is not supported");
302
+ return xhr;
303
+ };
304
+
305
+ /**
306
+ * Fetches a resource.
307
+ * @param {string} path Resource path
308
+ * @param {function(?string)=} callback Callback receiving the resource's contents. If omitted the resource will
309
+ * be fetched synchronously. If the request failed, contents will be null.
310
+ * @return {?string|undefined} Resource contents if callback is omitted (null if the request failed), else undefined.
311
+ * @expose
312
+ */
313
+ Util.fetch = function(path, callback) {
314
+ if (callback && typeof callback != 'function')
315
+ callback = null;
316
+ if (Util.IS_NODE) {
317
+ if (callback) {
318
+ require("fs").readFile(path, function(err, data) {
319
+ if (err)
320
+ callback(null);
321
+ else
322
+ callback(""+data);
323
+ });
324
+ } else
325
+ try {
326
+ return require("fs").readFileSync(path);
327
+ } catch (e) {
328
+ return null;
329
+ }
330
+ } else {
331
+ var xhr = Util.XHR();
332
+ xhr.open('GET', path, callback ? true : false);
333
+ // xhr.setRequestHeader('User-Agent', 'XMLHTTP/1.0');
334
+ xhr.setRequestHeader('Accept', 'text/plain');
335
+ if (typeof xhr.overrideMimeType === 'function') xhr.overrideMimeType('text/plain');
336
+ if (callback) {
337
+ xhr.onreadystatechange = function() {
338
+ if (xhr.readyState != 4) return;
339
+ if (/* remote */ xhr.status == 200 || /* local */ (xhr.status == 0 && typeof xhr.responseText === 'string'))
340
+ callback(xhr.responseText);
341
+ else
342
+ callback(null);
343
+ };
344
+ if (xhr.readyState == 4)
345
+ return;
346
+ xhr.send(null);
347
+ } else {
348
+ xhr.send(null);
349
+ if (/* remote */ xhr.status == 200 || /* local */ (xhr.status == 0 && typeof xhr.responseText === 'string'))
350
+ return xhr.responseText;
351
+ return null;
352
+ }
353
+ }
354
+ };
355
+
356
+ /**
357
+ * Tests if an object is an array.
358
+ * @function
359
+ * @param {*} obj Object to test
360
+ * @returns {boolean} true if it is an array, else false
361
+ * @expose
362
+ */
363
+ Util.isArray = Array.isArray || function(obj) {
364
+ return Object.prototype.toString.call(obj) === "[object Array]";
365
+ };
366
+
367
+ return Util;
368
+ })();
369
369
 
370
370
  /**
371
371
  * Language expressions.
@@ -402,7 +402,7 @@
402
402
  ID: /^(?:[1-9][0-9]*|0|0x[0-9a-fA-F]+|0[0-7]+)$/,
403
403
  NEGID: /^\-?(?:[1-9][0-9]*|0|0x[0-9a-fA-F]+|0[0-7]+)$/,
404
404
  WHITESPACE: /\s/,
405
- STRING: /['"]([^'"\\]*(\\.[^"\\]*)*)['"]/g,
405
+ STRING: /(?:"([^"\\]*(?:\\.[^"\\]*)*)")|(?:'([^'\\]*(?:\\.[^'\\]*)*)')/g,
406
406
  BOOL: /^(?:true|false)$/i
407
407
  };
408
408
 
@@ -423,7 +423,7 @@
423
423
  /**
424
424
  * Constructs a new Tokenizer.
425
425
  * @exports ProtoBuf.DotProto.Tokenizer
426
- * @class proto tokenizer
426
+ * @class prototype tokenizer
427
427
  * @param {string} proto Proto to tokenize
428
428
  * @constructor
429
429
  */
@@ -472,22 +472,28 @@
472
472
  this.stringEndsWith = Lang.STRINGCLOSE;
473
473
  };
474
474
 
475
+ /**
476
+ * @alias ProtoBuf.DotProto.Tokenizer.prototype
477
+ * @inner
478
+ */
479
+ var TokenizerPrototype = Tokenizer.prototype;
480
+
475
481
  /**
476
482
  * Reads a string beginning at the current index.
477
483
  * @return {string} The string
478
484
  * @throws {Error} If it's not a valid string
479
485
  * @private
480
486
  */
481
- Tokenizer.prototype._readString = function() {
487
+ TokenizerPrototype._readString = function() {
482
488
  Lang.STRING.lastIndex = this.index-1; // Include the open quote
483
489
  var match;
484
490
  if ((match = Lang.STRING.exec(this.source)) !== null) {
485
- var s = match[1];
491
+ var s = typeof match[1] !== 'undefined' ? match[1] : match[2];
486
492
  this.index = Lang.STRING.lastIndex;
487
493
  this.stack.push(this.stringEndsWith);
488
494
  return s;
489
495
  }
490
- throw Error("Illegal string value at line "+this.line+", index "+this.index);
496
+ throw Error("Unterminated string at line "+this.line+", index "+this.index);
491
497
  };
492
498
 
493
499
  /**
@@ -496,7 +502,7 @@
496
502
  * @throws {Error} If it's not a valid proto file
497
503
  * @expose
498
504
  */
499
- Tokenizer.prototype.next = function() {
505
+ TokenizerPrototype.next = function() {
500
506
  if (this.stack.length > 0)
501
507
  return this.stack.shift();
502
508
  if (this.index >= this.source.length)
@@ -539,7 +545,7 @@
539
545
  this.index++;
540
546
  repeat = true;
541
547
  } else
542
- throw Error("Invalid comment at line "+this.line+": /"+this.source.charAt(this.index)+" ('/' or '*' expected)");
548
+ throw Error("Unterminated comment at line "+this.line+": /"+this.source.charAt(this.index));
543
549
  }
544
550
  } while (repeat);
545
551
  if (this.index === this.source.length) return null;
@@ -570,7 +576,7 @@
570
576
  * @throws {Error} If it's not a valid proto file
571
577
  * @expose
572
578
  */
573
- Tokenizer.prototype.peek = function() {
579
+ TokenizerPrototype.peek = function() {
574
580
  if (this.stack.length === 0) {
575
581
  var token = this.next();
576
582
  if (token === null)
@@ -585,7 +591,7 @@
585
591
  * @return {string} String representation as of "Tokenizer(index/length)"
586
592
  * @expose
587
593
  */
588
- Tokenizer.prototype.toString = function() {
594
+ TokenizerPrototype.toString = function() {
589
595
  return "Tokenizer("+this.index+"/"+this.source.length+" at line "+this.line+")";
590
596
  };
591
597
 
@@ -598,7 +604,7 @@
598
604
  /**
599
605
  * Constructs a new Parser.
600
606
  * @exports ProtoBuf.DotProto.Parser
601
- * @class proto parser
607
+ * @class prototype parser
602
608
  * @param {string} proto Protocol source
603
609
  * @constructor
604
610
  */
@@ -612,13 +618,19 @@
612
618
  this.tn = new Tokenizer(proto);
613
619
  };
614
620
 
621
+ /**
622
+ * @alias ProtoBuf.DotProto.Parser.prototype
623
+ * @inner
624
+ */
625
+ var ParserPrototype = Parser.prototype;
626
+
615
627
  /**
616
628
  * Runs the parser.
617
629
  * @return {{package: string|null, messages: Array.<object>, enums: Array.<object>, imports: Array.<string>, options: object<string,*>}}
618
630
  * @throws {Error} If the source cannot be parsed
619
631
  * @expose
620
632
  */
621
- Parser.prototype.parse = function() {
633
+ ParserPrototype.parse = function() {
622
634
  var topLevel = {
623
635
  "name": "[ROOT]", // temporary
624
636
  "package": null,
@@ -633,12 +645,12 @@
633
645
  switch (token) {
634
646
  case 'package':
635
647
  if (!head || topLevel["package"] !== null)
636
- throw Error("Illegal package at line "+this.tn.line);
648
+ throw Error("Unexpected package at line "+this.tn.line);
637
649
  topLevel["package"] = this._parsePackage(token);
638
650
  break;
639
651
  case 'import':
640
652
  if (!head)
641
- throw Error("Illegal import at line "+this.tn.line);
653
+ throw Error("Unexpected import at line "+this.tn.line);
642
654
  topLevel.imports.push(this._parseImport(token));
643
655
  break;
644
656
  case 'message':
@@ -651,7 +663,7 @@
651
663
  break;
652
664
  case 'option':
653
665
  if (!head)
654
- throw Error("Illegal option at line "+this.tn.line);
666
+ throw Error("Unexpected option at line "+this.tn.line);
655
667
  this._parseOption(topLevel, token);
656
668
  break;
657
669
  case 'service':
@@ -664,7 +676,7 @@
664
676
  this._parseIgnoredStatement(topLevel, token);
665
677
  break;
666
678
  default:
667
- throw Error("Illegal token at line "+this.tn.line+": "+token);
679
+ throw Error("Unexpected token at line "+this.tn.line+": "+token);
668
680
  }
669
681
  }
670
682
  delete topLevel["name"];
@@ -678,7 +690,7 @@
678
690
  * @throws {Error} If the number value is invalid
679
691
  * @private
680
692
  */
681
- Parser.prototype._parseNumber = function(val) {
693
+ ParserPrototype._parseNumber = function(val) {
682
694
  var sign = 1;
683
695
  if (val.charAt(0) == '-')
684
696
  sign = -1,
@@ -696,18 +708,17 @@
696
708
 
697
709
  /**
698
710
  * Parses a (possibly multiline) string.
699
- * @param {string} context Context description
700
711
  * @returns {string}
701
712
  * @private
702
713
  */
703
- Parser.prototype._parseString = function(context) {
714
+ ParserPrototype._parseString = function() {
704
715
  var value = "", token;
705
716
  do {
706
717
  token = this.tn.next(); // Known to be = this.tn.stringEndsWith
707
718
  value += this.tn.next();
708
719
  token = this.tn.next();
709
720
  if (token !== this.tn.stringEndsWith)
710
- throw Error("Illegal end of string in "+context+" at line "+this.tn.line+": "+token+" ('"+this.tn.stringEndsWith+"' expected)");
721
+ throw Error("Illegal end of string at line "+this.tn.line+": "+token);
711
722
  token = this.tn.peek();
712
723
  } while (token === Lang.STRINGOPEN || token === Lang.STRINGOPEN_SQ);
713
724
  return value;
@@ -721,7 +732,7 @@
721
732
  * @throws {Error} If the ID value is invalid
722
733
  * @private
723
734
  */
724
- Parser.prototype._parseId = function(val, neg) {
735
+ ParserPrototype._parseId = function(val, neg) {
725
736
  var id = -1;
726
737
  var sign = 1;
727
738
  if (val.charAt(0) == '-')
@@ -734,10 +745,10 @@
734
745
  else if (Lang.NUMBER_OCT.test(val))
735
746
  id = parseInt(val.substring(1), 8);
736
747
  else
737
- throw Error("Illegal ID at line "+this.tn.line+": "+(sign < 0 ? '-' : '')+val);
748
+ throw Error("Illegal id at line "+this.tn.line+": "+(sign < 0 ? '-' : '')+val);
738
749
  id = (sign*id)|0; // Force to 32bit
739
750
  if (!neg && id < 0)
740
- throw Error("Illegal ID at line "+this.tn.line+": "+(sign < 0 ? '-' : '')+val);
751
+ throw Error("Illegal id at line "+this.tn.line+": "+(sign < 0 ? '-' : '')+val);
741
752
  return id;
742
753
  };
743
754
 
@@ -748,14 +759,14 @@
748
759
  * @throws {Error} If the package definition cannot be parsed
749
760
  * @private
750
761
  */
751
- Parser.prototype._parsePackage = function(token) {
762
+ ParserPrototype._parsePackage = function(token) {
752
763
  token = this.tn.next();
753
764
  if (!Lang.TYPEREF.test(token))
754
- throw Error("Illegal package at line "+this.tn.line+": "+token);
765
+ throw Error("Illegal package name at line "+this.tn.line+": "+token);
755
766
  var pkg = token;
756
767
  token = this.tn.next();
757
768
  if (token != Lang.END)
758
- throw Error("Illegal end of package at line "+this.tn.line+": "+token+" ('"+Lang.END+"' expected)");
769
+ throw Error("Illegal end of package at line "+this.tn.line+": "+token);
759
770
  return pkg;
760
771
  };
761
772
 
@@ -766,17 +777,17 @@
766
777
  * @throws {Error} If the import definition cannot be parsed
767
778
  * @private
768
779
  */
769
- Parser.prototype._parseImport = function(token) {
780
+ ParserPrototype._parseImport = function(token) {
770
781
  token = this.tn.peek();
771
782
  if (token === "public")
772
783
  this.tn.next(),
773
784
  token = this.tn.peek();
774
785
  if (token !== Lang.STRINGOPEN && token !== Lang.STRINGOPEN_SQ)
775
- throw Error("Illegal import at line "+this.tn.line+": "+token+" ('"+Lang.STRINGOPEN+"' or '"+Lang.STRINGOPEN_SQ+"' expected)");
776
- var imported = this._parseString("root");
786
+ throw Error("Illegal start of import at line "+this.tn.line+": "+token);
787
+ var imported = this._parseString();
777
788
  token = this.tn.next();
778
789
  if (token !== Lang.END)
779
- throw Error("Illegal import at line "+this.tn.line+": "+token+" ('"+Lang.END+"' expected)");
790
+ throw Error("Illegal end of import at line "+this.tn.line+": "+token);
780
791
  return imported;
781
792
  };
782
793
 
@@ -787,7 +798,7 @@
787
798
  * @throws {Error} If the option cannot be parsed
788
799
  * @private
789
800
  */
790
- Parser.prototype._parseOption = function(parent, token) {
801
+ ParserPrototype._parseOption = function(parent, token) {
791
802
  token = this.tn.next();
792
803
  var custom = false;
793
804
  if (token == Lang.COPTOPEN)
@@ -796,12 +807,12 @@
796
807
  if (!Lang.TYPEREF.test(token))
797
808
  // we can allow options of the form google.protobuf.* since they will just get ignored anyways
798
809
  if (!/google\.protobuf\./.test(token))
799
- throw Error("Illegal option in message "+parent.name+" at line "+this.tn.line+": "+token);
810
+ throw Error("Illegal option name in message "+parent.name+" at line "+this.tn.line+": "+token);
800
811
  var name = token;
801
812
  token = this.tn.next();
802
813
  if (custom) { // (my_method_option).foo, (my_method_option), some_method_option, (foo.my_option).bar
803
814
  if (token !== Lang.COPTCLOSE)
804
- throw Error("Illegal option in message "+parent.name+", option "+name+" at line "+this.tn.line+": "+token+" ('"+Lang.COPTCLOSE+"' expected)");
815
+ throw Error("Illegal end in message "+parent.name+", option "+name+" at line "+this.tn.line+": "+token);
805
816
  name = '('+name+')';
806
817
  token = this.tn.next();
807
818
  if (Lang.FQTYPEREF.test(token))
@@ -809,11 +820,11 @@
809
820
  token = this.tn.next();
810
821
  }
811
822
  if (token !== Lang.EQUAL)
812
- throw Error("Illegal option operator in message "+parent.name+", option "+name+" at line "+this.tn.line+": "+token+" ('"+Lang.EQUAL+"' expected)");
823
+ throw Error("Illegal operator in message "+parent.name+", option "+name+" at line "+this.tn.line+": "+token);
813
824
  var value;
814
825
  token = this.tn.peek();
815
826
  if (token === Lang.STRINGOPEN || token === Lang.STRINGOPEN_SQ)
816
- value = this._parseString("message "+parent.name+", option "+name);
827
+ value = this._parseString();
817
828
  else {
818
829
  this.tn.next();
819
830
  if (Lang.NUMBER.test(token))
@@ -827,7 +838,7 @@
827
838
  }
828
839
  token = this.tn.next();
829
840
  if (token !== Lang.END)
830
- throw Error("Illegal end of option in message "+parent.name+", option "+name+" at line "+this.tn.line+": "+token+" ('"+Lang.END+"' expected)");
841
+ throw Error("Illegal end of option in message "+parent.name+", option "+name+" at line "+this.tn.line+": "+token);
831
842
  parent["options"][name] = value;
832
843
  };
833
844
 
@@ -838,12 +849,12 @@
838
849
  * @throws {Error} If the directive cannot be parsed
839
850
  * @private
840
851
  */
841
- Parser.prototype._parseIgnoredStatement = function(parent, keyword) {
852
+ ParserPrototype._parseIgnoredStatement = function(parent, keyword) {
842
853
  var token;
843
854
  do {
844
855
  token = this.tn.next();
845
856
  if (token === null)
846
- throw Error("Unexpected EOF in "+parent.name+", "+keyword+" (ignored) at line "+this.tn.line);
857
+ throw Error("Unexpected EOF in "+parent.name+", "+keyword+" at line "+this.tn.line);
847
858
  if (token === Lang.END)
848
859
  break;
849
860
  } while (true);
@@ -856,7 +867,7 @@
856
867
  * @throws {Error} If the service cannot be parsed
857
868
  * @private
858
869
  */
859
- Parser.prototype._parseService = function(parent, token) {
870
+ ParserPrototype._parseService = function(parent, token) {
860
871
  token = this.tn.next();
861
872
  if (!Lang.NAME.test(token))
862
873
  throw Error("Illegal service name at line "+this.tn.line+": "+token);
@@ -868,7 +879,7 @@
868
879
  };
869
880
  token = this.tn.next();
870
881
  if (token !== Lang.OPEN)
871
- throw Error("Illegal OPEN after service "+name+" at line "+this.tn.line+": "+token+" ('"+Lang.OPEN+"' expected)");
882
+ throw Error("Illegal start of service "+name+" at line "+this.tn.line+": "+token);
872
883
  do {
873
884
  token = this.tn.next();
874
885
  if (token === "option")
@@ -876,7 +887,7 @@
876
887
  else if (token === 'rpc')
877
888
  this._parseServiceRPC(svc, token);
878
889
  else if (token !== Lang.CLOSE)
879
- throw Error("Illegal type for service "+name+" at line "+this.tn.line+": "+token);
890
+ throw Error("Illegal type of service "+name+" at line "+this.tn.line+": "+token);
880
891
  } while (token !== Lang.CLOSE);
881
892
  parent["services"].push(svc);
882
893
  };
@@ -887,11 +898,11 @@
887
898
  * @param {string} token Initial token
888
899
  * @private
889
900
  */
890
- Parser.prototype._parseServiceRPC = function(svc, token) {
901
+ ParserPrototype._parseServiceRPC = function(svc, token) {
891
902
  var type = token;
892
903
  token = this.tn.next();
893
904
  if (!Lang.NAME.test(token))
894
- throw Error("Illegal RPC method name in service "+svc["name"]+" at line "+this.tn.line+": "+token);
905
+ throw Error("Illegal method name in service "+svc["name"]+" at line "+this.tn.line+": "+token);
895
906
  var name = token;
896
907
  var method = {
897
908
  "request": null,
@@ -900,25 +911,25 @@
900
911
  };
901
912
  token = this.tn.next();
902
913
  if (token !== Lang.COPTOPEN)
903
- throw Error("Illegal start of request type in RPC service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token+" ('"+Lang.COPTOPEN+"' expected)");
914
+ throw Error("Illegal start of request type in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
904
915
  token = this.tn.next();
905
916
  if (!Lang.TYPEREF.test(token))
906
- throw Error("Illegal request type in RPC service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
917
+ throw Error("Illegal request type in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
907
918
  method["request"] = token;
908
919
  token = this.tn.next();
909
920
  if (token != Lang.COPTCLOSE)
910
- throw Error("Illegal end of request type in RPC service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token+" ('"+Lang.COPTCLOSE+"' expected)");
921
+ throw Error("Illegal end of request type in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
911
922
  token = this.tn.next();
912
923
  if (token.toLowerCase() !== "returns")
913
- throw Error("Illegal request/response delimiter in RPC service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token+" ('returns' expected)");
924
+ throw Error("Illegal delimiter in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
914
925
  token = this.tn.next();
915
926
  if (token != Lang.COPTOPEN)
916
- throw Error("Illegal start of response type in RPC service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token+" ('"+Lang.COPTOPEN+"' expected)");
927
+ throw Error("Illegal start of response type in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
917
928
  token = this.tn.next();
918
929
  method["response"] = token;
919
930
  token = this.tn.next();
920
931
  if (token !== Lang.COPTCLOSE)
921
- throw Error("Illegal end of response type in RPC service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token+" ('"+Lang.COPTCLOSE+"' expected)");
932
+ throw Error("Illegal end of response type in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
922
933
  token = this.tn.next();
923
934
  if (token === Lang.OPEN) {
924
935
  do {
@@ -926,12 +937,12 @@
926
937
  if (token === 'option')
927
938
  this._parseOption(method, token); // <- will fail for the custom-options example
928
939
  else if (token !== Lang.CLOSE)
929
- throw Error("Illegal start of option in RPC service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token+" ('option' expected)");
940
+ throw Error("Illegal start of option inservice "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
930
941
  } while (token !== Lang.CLOSE);
931
942
  if (this.tn.peek() === Lang.END)
932
943
  this.tn.next();
933
944
  } else if (token !== Lang.END)
934
- throw Error("Illegal method delimiter in RPC service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token+" ('"+Lang.END+"' or '"+Lang.OPEN+"' expected)");
945
+ throw Error("Illegal delimiter in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
935
946
  if (typeof svc[type] === 'undefined')
936
947
  svc[type] = {};
937
948
  svc[type][name] = method;
@@ -946,7 +957,7 @@
946
957
  * @throws {Error} If the message cannot be parsed
947
958
  * @private
948
959
  */
949
- Parser.prototype._parseMessage = function(parent, fld, token) {
960
+ ParserPrototype._parseMessage = function(parent, fld, token) {
950
961
  /** @dict */
951
962
  var msg = {}; // Note: At some point we might want to exclude the parser, so we need a dict.
952
963
  var isGroup = token === "group";
@@ -957,7 +968,7 @@
957
968
  if (isGroup) {
958
969
  token = this.tn.next();
959
970
  if (token !== Lang.EQUAL)
960
- throw Error("Illegal id assignment after group "+msg.name+" at line "+this.tn.line+": "+token+" ('"+Lang.EQUAL+"' expected)");
971
+ throw Error("Illegal id assignment after group "+msg.name+" at line "+this.tn.line+": "+token);
961
972
  token = this.tn.next();
962
973
  try {
963
974
  fld["id"] = this._parseId(token);
@@ -970,12 +981,13 @@
970
981
  msg["enums"] = [];
971
982
  msg["messages"] = [];
972
983
  msg["options"] = {};
984
+ msg["oneofs"] = {};
973
985
  token = this.tn.next();
974
986
  if (token === Lang.OPTOPEN && fld)
975
987
  this._parseFieldOptions(msg, fld, token),
976
988
  token = this.tn.next();
977
989
  if (token !== Lang.OPEN)
978
- throw Error("Illegal OPEN after "+(isGroup ? "group" : "message")+" "+msg.name+" at line "+this.tn.line+": "+token+" ('"+Lang.OPEN+"' expected)");
990
+ throw Error("Illegal start of "+(isGroup ? "group" : "message")+" "+msg.name+" at line "+this.tn.line+": "+token);
979
991
  // msg["extensions"] = undefined
980
992
  do {
981
993
  token = this.tn.next();
@@ -986,6 +998,8 @@
986
998
  break;
987
999
  } else if (Lang.RULE.test(token))
988
1000
  this._parseMessageField(msg, token);
1001
+ else if (token === "oneof")
1002
+ this._parseMessageOneOf(msg, token);
989
1003
  else if (token === "enum")
990
1004
  this._parseEnum(msg, token);
991
1005
  else if (token === "message")
@@ -997,7 +1011,7 @@
997
1011
  else if (token === "extend")
998
1012
  this._parseExtend(msg, token);
999
1013
  else
1000
- throw Error("Illegal token in message "+msg.name+" at line "+this.tn.line+": "+token+" (type or '"+Lang.CLOSE+"' expected)");
1014
+ throw Error("Illegal token in message "+msg.name+" at line "+this.tn.line+": "+token);
1001
1015
  } while (true);
1002
1016
  parent["messages"].push(msg);
1003
1017
  return msg;
@@ -1007,10 +1021,11 @@
1007
1021
  * Parses a message field.
1008
1022
  * @param {Object} msg Message definition
1009
1023
  * @param {string} token Initial token
1024
+ * @returns {!Object} Field descriptor
1010
1025
  * @throws {Error} If the message field cannot be parsed
1011
1026
  * @private
1012
1027
  */
1013
- Parser.prototype._parseMessageField = function(msg, token) {
1028
+ ParserPrototype._parseMessageField = function(msg, token) {
1014
1029
  /** @dict */
1015
1030
  var fld = {}, grp = null;
1016
1031
  fld["rule"] = token;
@@ -1039,21 +1054,48 @@
1039
1054
  fld["name"] = token;
1040
1055
  token = this.tn.next();
1041
1056
  if (token !== Lang.EQUAL)
1042
- throw Error("Illegal field id assignment in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token+" ('"+Lang.EQUAL+"' expected)");
1057
+ throw Error("Illegal token in field "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
1043
1058
  token = this.tn.next();
1044
1059
  try {
1045
1060
  fld["id"] = this._parseId(token);
1046
1061
  } catch (e) {
1047
- throw Error("Illegal field id value in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
1062
+ throw Error("Illegal field id in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
1048
1063
  }
1049
1064
  token = this.tn.next();
1050
1065
  if (token === Lang.OPTOPEN)
1051
1066
  this._parseFieldOptions(msg, fld, token),
1052
1067
  token = this.tn.next();
1053
1068
  if (token !== Lang.END)
1054
- throw Error("Illegal field delimiter in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token+" ('"+Lang.END+"' expected)");
1069
+ throw Error("Illegal delimiter in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
1055
1070
  }
1056
1071
  msg["fields"].push(fld);
1072
+ return fld;
1073
+ };
1074
+
1075
+ /**
1076
+ * Parses a message oneof.
1077
+ * @param {Object} msg Message definition
1078
+ * @param {string} token Initial token
1079
+ * @throws {Error} If the message oneof cannot be parsed
1080
+ * @private
1081
+ */
1082
+ ParserPrototype._parseMessageOneOf = function(msg, token) {
1083
+ token = this.tn.next();
1084
+ if (!Lang.NAME.test(token))
1085
+ throw Error("Illegal oneof name in message "+msg.name+" at line "+this.tn.line+": "+token);
1086
+ var name = token,
1087
+ fld;
1088
+ var fields = [];
1089
+ token = this.tn.next();
1090
+ if (token !== Lang.OPEN)
1091
+ throw Error("Illegal start of oneof "+name+" at line "+this.tn.line+": "+token);
1092
+ while (this.tn.peek() !== Lang.CLOSE) {
1093
+ fld = this._parseMessageField(msg, "optional");
1094
+ fld["oneof"] = name;
1095
+ fields.push(fld["id"]);
1096
+ }
1097
+ this.tn.next();
1098
+ msg["oneofs"][name] = fields;
1057
1099
  };
1058
1100
 
1059
1101
  /**
@@ -1064,7 +1106,7 @@
1064
1106
  * @throws {Error} If the message field options cannot be parsed
1065
1107
  * @private
1066
1108
  */
1067
- Parser.prototype._parseFieldOptions = function(msg, fld, token) {
1109
+ ParserPrototype._parseFieldOptions = function(msg, fld, token) {
1068
1110
  var first = true;
1069
1111
  do {
1070
1112
  token = this.tn.next();
@@ -1072,7 +1114,7 @@
1072
1114
  break;
1073
1115
  else if (token === Lang.OPTEND) {
1074
1116
  if (first)
1075
- throw Error("Illegal start of message field options in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
1117
+ throw Error("Illegal start of options in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
1076
1118
  token = this.tn.next();
1077
1119
  }
1078
1120
  this._parseFieldOption(msg, fld, token);
@@ -1088,18 +1130,18 @@
1088
1130
  * @throws {Error} If the mesage field option cannot be parsed
1089
1131
  * @private
1090
1132
  */
1091
- Parser.prototype._parseFieldOption = function(msg, fld, token) {
1133
+ ParserPrototype._parseFieldOption = function(msg, fld, token) {
1092
1134
  var custom = false;
1093
1135
  if (token === Lang.COPTOPEN)
1094
1136
  token = this.tn.next(),
1095
1137
  custom = true;
1096
1138
  if (!Lang.TYPEREF.test(token))
1097
- throw Error("Illegal field option in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
1139
+ throw Error("Illegal field option in "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
1098
1140
  var name = token;
1099
1141
  token = this.tn.next();
1100
1142
  if (custom) {
1101
1143
  if (token !== Lang.COPTCLOSE)
1102
- throw Error("Illegal custom field option name delimiter in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token+" (')' expected)");
1144
+ throw Error("Illegal delimiter in "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
1103
1145
  name = '('+name+')';
1104
1146
  token = this.tn.next();
1105
1147
  if (Lang.FQTYPEREF.test(token))
@@ -1107,11 +1149,11 @@
1107
1149
  token = this.tn.next();
1108
1150
  }
1109
1151
  if (token !== Lang.EQUAL)
1110
- throw Error("Illegal field option operation in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token+" ('=' expected)");
1152
+ throw Error("Illegal token in "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
1111
1153
  var value;
1112
1154
  token = this.tn.peek();
1113
1155
  if (token === Lang.STRINGOPEN || token === Lang.STRINGOPEN_SQ) {
1114
- value = this._parseString("message "+msg.name+"#"+fld.name);
1156
+ value = this._parseString();
1115
1157
  } else if (Lang.NUMBER.test(token, true))
1116
1158
  value = this._parseNumber(this.tn.next(), true);
1117
1159
  else if (Lang.BOOL.test(token))
@@ -1119,7 +1161,7 @@
1119
1161
  else if (Lang.TYPEREF.test(token))
1120
1162
  value = this.tn.next(); // TODO: Resolve?
1121
1163
  else
1122
- throw Error("Illegal field option value in message "+msg.name+"#"+fld.name+", option "+name+" at line "+this.tn.line+": "+token);
1164
+ throw Error("Illegal value in message "+msg.name+"#"+fld.name+", option "+name+" at line "+this.tn.line+": "+token);
1123
1165
  fld["options"][name] = value;
1124
1166
  };
1125
1167
 
@@ -1130,7 +1172,7 @@
1130
1172
  * @throws {Error} If the enum cannot be parsed
1131
1173
  * @private
1132
1174
  */
1133
- Parser.prototype._parseEnum = function(msg, token) {
1175
+ ParserPrototype._parseEnum = function(msg, token) {
1134
1176
  /** @dict */
1135
1177
  var enm = {};
1136
1178
  token = this.tn.next();
@@ -1139,7 +1181,7 @@
1139
1181
  enm["name"] = token;
1140
1182
  token = this.tn.next();
1141
1183
  if (token !== Lang.OPEN)
1142
- throw Error("Illegal OPEN after enum "+enm.name+" at line "+this.tn.line+": "+token);
1184
+ throw Error("Illegal start of enum "+enm.name+" at line "+this.tn.line+": "+token);
1143
1185
  enm["values"] = [];
1144
1186
  enm["options"] = {};
1145
1187
  do {
@@ -1154,7 +1196,7 @@
1154
1196
  this._parseOption(enm, token);
1155
1197
  else {
1156
1198
  if (!Lang.NAME.test(token))
1157
- throw Error("Illegal enum value name in enum "+enm.name+" at line "+this.tn.line+": "+token);
1199
+ throw Error("Illegal name in enum "+enm.name+" at line "+this.tn.line+": "+token);
1158
1200
  this._parseEnumValue(enm, token);
1159
1201
  }
1160
1202
  } while (true);
@@ -1168,18 +1210,18 @@
1168
1210
  * @throws {Error} If the enum value cannot be parsed
1169
1211
  * @private
1170
1212
  */
1171
- Parser.prototype._parseEnumValue = function(enm, token) {
1213
+ ParserPrototype._parseEnumValue = function(enm, token) {
1172
1214
  /** @dict */
1173
1215
  var val = {};
1174
1216
  val["name"] = token;
1175
1217
  token = this.tn.next();
1176
1218
  if (token !== Lang.EQUAL)
1177
- throw Error("Illegal enum value operator in enum "+enm.name+" at line "+this.tn.line+": "+token+" ('"+Lang.EQUAL+"' expected)");
1219
+ throw Error("Illegal token in enum "+enm.name+" at line "+this.tn.line+": "+token);
1178
1220
  token = this.tn.next();
1179
1221
  try {
1180
1222
  val["id"] = this._parseId(token, true);
1181
1223
  } catch (e) {
1182
- throw Error("Illegal enum value id in enum "+enm.name+" at line "+this.tn.line+": "+token);
1224
+ throw Error("Illegal id in enum "+enm.name+" at line "+this.tn.line+": "+token);
1183
1225
  }
1184
1226
  enm["values"].push(val);
1185
1227
  token = this.tn.next();
@@ -1189,7 +1231,7 @@
1189
1231
  token = this.tn.next();
1190
1232
  }
1191
1233
  if (token !== Lang.END)
1192
- throw Error("Illegal enum value delimiter in enum "+enm.name+" at line "+this.tn.line+": "+token+" ('"+Lang.END+"' expected)");
1234
+ throw Error("Illegal delimiter in enum "+enm.name+" at line "+this.tn.line+": "+token);
1193
1235
  };
1194
1236
 
1195
1237
  /**
@@ -1199,7 +1241,7 @@
1199
1241
  * @throws {Error} If the extensions statement cannot be parsed
1200
1242
  * @private
1201
1243
  */
1202
- Parser.prototype._parseExtensions = function(msg, token) {
1244
+ ParserPrototype._parseExtensions = function(msg, token) {
1203
1245
  /** @type {Array.<number>} */
1204
1246
  var range = [];
1205
1247
  token = this.tn.next();
@@ -1211,7 +1253,7 @@
1211
1253
  range.push(this._parseNumber(token));
1212
1254
  token = this.tn.next();
1213
1255
  if (token !== 'to')
1214
- throw Error("Illegal extensions delimiter in message "+msg.name+" at line "+this.tn.line+" ('to' expected)");
1256
+ throw Error("Illegal extensions delimiter in message "+msg.name+" at line "+this.tn.line+": "+token);
1215
1257
  token = this.tn.next();
1216
1258
  if (token === "min")
1217
1259
  range.push(ProtoBuf.ID_MIN);
@@ -1221,7 +1263,7 @@
1221
1263
  range.push(this._parseNumber(token));
1222
1264
  token = this.tn.next();
1223
1265
  if (token !== Lang.END)
1224
- throw Error("Illegal extension delimiter in message "+msg.name+" at line "+this.tn.line+": "+token+" ('"+Lang.END+"' expected)");
1266
+ throw Error("Illegal extensions delimiter in message "+msg.name+" at line "+this.tn.line+": "+token);
1225
1267
  return range;
1226
1268
  };
1227
1269
 
@@ -1232,17 +1274,17 @@
1232
1274
  * @throws {Error} If the extend block cannot be parsed
1233
1275
  * @private
1234
1276
  */
1235
- Parser.prototype._parseExtend = function(parent, token) {
1277
+ ParserPrototype._parseExtend = function(parent, token) {
1236
1278
  token = this.tn.next();
1237
1279
  if (!Lang.TYPEREF.test(token))
1238
- throw Error("Illegal extended message name at line "+this.tn.line+": "+token);
1280
+ throw Error("Illegal message name at line "+this.tn.line+": "+token);
1239
1281
  /** @dict */
1240
1282
  var ext = {};
1241
1283
  ext["ref"] = token;
1242
1284
  ext["fields"] = [];
1243
1285
  token = this.tn.next();
1244
1286
  if (token !== Lang.OPEN)
1245
- throw Error("Illegal OPEN in extend "+ext.name+" at line "+this.tn.line+": "+token+" ('"+Lang.OPEN+"' expected)");
1287
+ throw Error("Illegal start of extend "+ext.name+" at line "+this.tn.line+": "+token);
1246
1288
  do {
1247
1289
  token = this.tn.next();
1248
1290
  if (token === Lang.CLOSE) {
@@ -1253,7 +1295,7 @@
1253
1295
  } else if (Lang.RULE.test(token))
1254
1296
  this._parseMessageField(ext, token);
1255
1297
  else
1256
- throw Error("Illegal token in extend "+ext.name+" at line "+this.tn.line+": "+token+" (rule or '"+Lang.CLOSE+"' expected)");
1298
+ throw Error("Illegal token in extend "+ext.name+" at line "+this.tn.line+": "+token);
1257
1299
  } while (true);
1258
1300
  parent["messages"].push(ext);
1259
1301
  return ext;
@@ -1263,7 +1305,7 @@
1263
1305
  * Returns a string representation of this object.
1264
1306
  * @returns {string} String representation as of "Parser"
1265
1307
  */
1266
- Parser.prototype.toString = function() {
1308
+ ParserPrototype.toString = function() {
1267
1309
  return "Parser";
1268
1310
  };
1269
1311
 
@@ -1296,14 +1338,22 @@
1296
1338
  * @exports ProtoBuf.Reflect.T
1297
1339
  * @constructor
1298
1340
  * @abstract
1299
- * @param {ProtoBuf.Reflect.T} parent Parent object
1341
+ * @param {!ProtoBuf.Builder} builder Builder reference
1342
+ * @param {?ProtoBuf.Reflect.T} parent Parent object
1300
1343
  * @param {string} name Object name
1301
1344
  */
1302
- var T = function(parent, name) {
1345
+ var T = function(builder, parent, name) {
1346
+
1347
+ /**
1348
+ * Builder reference.
1349
+ * @type {!ProtoBuf.Builder}
1350
+ * @expose
1351
+ */
1352
+ this.builder = builder;
1303
1353
 
1304
1354
  /**
1305
1355
  * Parent object.
1306
- * @type {ProtoBuf.Reflect.T|null}
1356
+ * @type {?ProtoBuf.Reflect.T}
1307
1357
  * @expose
1308
1358
  */
1309
1359
  this.parent = parent;
@@ -1323,12 +1373,18 @@
1323
1373
  this.className;
1324
1374
  };
1325
1375
 
1376
+ /**
1377
+ * @alias ProtoBuf.Reflect.T.prototype
1378
+ * @inner
1379
+ */
1380
+ var TPrototype = T.prototype;
1381
+
1326
1382
  /**
1327
1383
  * Returns the fully qualified name of this object.
1328
1384
  * @returns {string} Fully qualified name as of ".PATH.TO.THIS"
1329
1385
  * @expose
1330
1386
  */
1331
- T.prototype.fqn = function() {
1387
+ TPrototype.fqn = function() {
1332
1388
  var name = this.name,
1333
1389
  ptr = this;
1334
1390
  do {
@@ -1346,7 +1402,7 @@
1346
1402
  * @return String representation
1347
1403
  * @expose
1348
1404
  */
1349
- T.prototype.toString = function(includeClass) {
1405
+ TPrototype.toString = function(includeClass) {
1350
1406
  return (includeClass ? this.className + " " : "") + this.fqn();
1351
1407
  };
1352
1408
 
@@ -1355,7 +1411,7 @@
1355
1411
  * @throws {Error} If this type cannot be built directly
1356
1412
  * @expose
1357
1413
  */
1358
- T.prototype.build = function() {
1414
+ TPrototype.build = function() {
1359
1415
  throw Error(this.toString(true)+" cannot be built directly");
1360
1416
  };
1361
1417
 
@@ -1368,14 +1424,15 @@
1368
1424
  /**
1369
1425
  * Constructs a new Namespace.
1370
1426
  * @exports ProtoBuf.Reflect.Namespace
1371
- * @param {ProtoBuf.Reflect.Namespace|null} parent Namespace parent
1427
+ * @param {!ProtoBuf.Builder} builder Builder reference
1428
+ * @param {?ProtoBuf.Reflect.Namespace} parent Namespace parent
1372
1429
  * @param {string} name Namespace name
1373
- * @param {Object.<string,*>} options Namespace options
1430
+ * @param {Object.<string,*>=} options Namespace options
1374
1431
  * @constructor
1375
1432
  * @extends ProtoBuf.Reflect.T
1376
1433
  */
1377
- var Namespace = function(parent, name, options) {
1378
- T.call(this, parent, name);
1434
+ var Namespace = function(builder, parent, name, options) {
1435
+ T.call(this, builder, parent, name);
1379
1436
 
1380
1437
  /**
1381
1438
  * @override
@@ -1384,19 +1441,22 @@
1384
1441
 
1385
1442
  /**
1386
1443
  * Children inside the namespace.
1387
- * @type {Array.<ProtoBuf.Reflect.T>}
1444
+ * @type {!Array.<ProtoBuf.Reflect.T>}
1388
1445
  */
1389
1446
  this.children = [];
1390
1447
 
1391
1448
  /**
1392
1449
  * Options.
1393
- * @type {Object.<string, *>}
1450
+ * @type {!Object.<string, *>}
1394
1451
  */
1395
1452
  this.options = options || {};
1396
1453
  };
1397
1454
 
1398
- // Extends T
1399
- Namespace.prototype = Object.create(T.prototype);
1455
+ /**
1456
+ * @alias ProtoBuf.Reflect.Namespace.prototype
1457
+ * @inner
1458
+ */
1459
+ var NamespacePrototype = Namespace.prototype = Object.create(T.prototype);
1400
1460
 
1401
1461
  /**
1402
1462
  * Returns an array of the namespace's children.
@@ -1404,7 +1464,7 @@
1404
1464
  * @return {Array.<ProtoBuf.Reflect.T>}
1405
1465
  * @expose
1406
1466
  */
1407
- Namespace.prototype.getChildren = function(type) {
1467
+ NamespacePrototype.getChildren = function(type) {
1408
1468
  type = type || null;
1409
1469
  if (type == null)
1410
1470
  return this.children.slice();
@@ -1421,7 +1481,7 @@
1421
1481
  * @throws {Error} If the child cannot be added (duplicate)
1422
1482
  * @expose
1423
1483
  */
1424
- Namespace.prototype.addChild = function(child) {
1484
+ NamespacePrototype.addChild = function(child) {
1425
1485
  var other;
1426
1486
  if (other = this.getChild(child.name)) {
1427
1487
  // Try to revert camelcase transformation on collision
@@ -1441,7 +1501,7 @@
1441
1501
  * @return {?ProtoBuf.Reflect.T} The child or null if not found
1442
1502
  * @expose
1443
1503
  */
1444
- Namespace.prototype.getChild = function(nameOrId) {
1504
+ NamespacePrototype.getChild = function(nameOrId) {
1445
1505
  var key = typeof nameOrId === 'number' ? 'id' : 'name';
1446
1506
  for (var i=0, k=this.children.length; i<k; ++i)
1447
1507
  if (this.children[i][key] === nameOrId)
@@ -1456,7 +1516,7 @@
1456
1516
  * @return {?ProtoBuf.Reflect.Namespace} The resolved type or null if not found
1457
1517
  * @expose
1458
1518
  */
1459
- Namespace.prototype.resolve = function(qn, excludeFields) {
1519
+ NamespacePrototype.resolve = function(qn, excludeFields) {
1460
1520
  var part = qn.split("."),
1461
1521
  ptr = this,
1462
1522
  i = 0;
@@ -1490,7 +1550,7 @@
1490
1550
  * @return {Object.<string,Function|Object>} Runtime namespace
1491
1551
  * @expose
1492
1552
  */
1493
- Namespace.prototype.build = function() {
1553
+ NamespacePrototype.build = function() {
1494
1554
  /** @dict */
1495
1555
  var ns = {};
1496
1556
  var children = this.children;
@@ -1508,7 +1568,7 @@
1508
1568
  * Builds the namespace's '$options' property.
1509
1569
  * @return {Object.<string,*>}
1510
1570
  */
1511
- Namespace.prototype.buildOpt = function() {
1571
+ NamespacePrototype.buildOpt = function() {
1512
1572
  var opt = {},
1513
1573
  keys = Object.keys(this.options);
1514
1574
  for (var i=0, k=keys.length; i<k; ++i) {
@@ -1529,7 +1589,7 @@
1529
1589
  * @param {string=} name Returns the option value if specified, otherwise all options are returned.
1530
1590
  * @return {*|Object.<string,*>}null} Option value or NULL if there is no such option
1531
1591
  */
1532
- Namespace.prototype.getOption = function(name) {
1592
+ NamespacePrototype.getOption = function(name) {
1533
1593
  if (typeof name === 'undefined')
1534
1594
  return this.options;
1535
1595
  return typeof this.options[name] !== 'undefined' ? this.options[name] : null;
@@ -1544,15 +1604,16 @@
1544
1604
  /**
1545
1605
  * Constructs a new Message.
1546
1606
  * @exports ProtoBuf.Reflect.Message
1547
- * @param {ProtoBuf.Reflect.Namespace} parent Parent message or namespace
1607
+ * @param {!ProtoBuf.Builder} builder Builder reference
1608
+ * @param {!ProtoBuf.Reflect.Namespace} parent Parent message or namespace
1548
1609
  * @param {string} name Message name
1549
- * @param {Object.<string,*>} options Message options
1610
+ * @param {Object.<string,*>=} options Message options
1550
1611
  * @param {boolean=} isGroup `true` if this is a legacy group
1551
1612
  * @constructor
1552
1613
  * @extends ProtoBuf.Reflect.Namespace
1553
1614
  */
1554
- var Message = function(parent, name, options, isGroup) {
1555
- Namespace.call(this, parent, name, options);
1615
+ var Message = function(builder, parent, name, options, isGroup) {
1616
+ Namespace.call(this, builder, parent, name, options);
1556
1617
 
1557
1618
  /**
1558
1619
  * @override
@@ -1595,10 +1656,20 @@
1595
1656
  * @private
1596
1657
  */
1597
1658
  this._fieldsById = null;
1659
+
1660
+ /**
1661
+ * Cached fields by name.
1662
+ * @type {?Object.<string,!ProtoBuf.Reflect.Message.Field>}
1663
+ * @private
1664
+ */
1665
+ this._fieldsByName = null;
1598
1666
  };
1599
1667
 
1600
- // Extends Namespace
1601
- Message.prototype = Object.create(Namespace.prototype);
1668
+ /**
1669
+ * @alias ProtoBuf.Reflect.Message.prototype
1670
+ * @inner
1671
+ */
1672
+ var MessagePrototype = Message.prototype = Object.create(Namespace.prototype);
1602
1673
 
1603
1674
  /**
1604
1675
  * Builds the message and returns the runtime counterpart, which is a fully functional class.
@@ -1608,14 +1679,15 @@
1608
1679
  * @throws {Error} If the message cannot be built
1609
1680
  * @expose
1610
1681
  */
1611
- Message.prototype.build = function(rebuild) {
1682
+ MessagePrototype.build = function(rebuild) {
1612
1683
  if (this.clazz && !rebuild)
1613
1684
  return this.clazz;
1614
1685
 
1615
1686
  // Create the runtime Message class in its own scope
1616
1687
  var clazz = (function(ProtoBuf, T) {
1617
1688
 
1618
- var fields = T.getChildren(ProtoBuf.Reflect.Message.Field);
1689
+ var fields = T.getChildren(ProtoBuf.Reflect.Message.Field),
1690
+ oneofs = T.getChildren(ProtoBuf.Reflect.Message.OneOf);
1619
1691
 
1620
1692
  /**
1621
1693
  * Constructs a new runtime Message.
@@ -1629,9 +1701,13 @@
1629
1701
  var Message = function(values, var_args) {
1630
1702
  ProtoBuf.Builder.Message.call(this);
1631
1703
 
1632
- // Create fields on the object itself and set default values
1633
- for (var i=0, k=fields.length, field; i<k; ++i) {
1634
- this[(field = fields[i]).name] = field.repeated ? [] : null;
1704
+ // Create virtual oneof properties
1705
+ for (var i=0, k=oneofs.length; i<k; ++i)
1706
+ this[oneofs[i].name] = null;
1707
+ // Create fields and set default values
1708
+ for (i=0, k=fields.length; i<k; ++i) {
1709
+ var field = fields[i];
1710
+ this[field.name] = field.repeated ? [] : null;
1635
1711
  if (field.required && field.defaultValue !== null)
1636
1712
  this[field.name] = field.defaultValue;
1637
1713
  }
@@ -1647,21 +1723,17 @@
1647
1723
  var keys = Object.keys(values);
1648
1724
  for (i=0, k=keys.length; i<k; ++i)
1649
1725
  this.$set(keys[i], values[keys[i]]); // May throw
1650
- } else // set field values from arguments, in declaration order
1726
+ } else // Set field values from arguments, in declaration order
1651
1727
  for (i=0, k=arguments.length; i<k; ++i)
1652
1728
  this.$set(fields[i].name, arguments[i]); // May throw
1653
1729
  }
1654
1730
  };
1655
1731
 
1656
1732
  /**
1657
- * The message's reflection type.
1658
- * @name ProtoBuf.Builder.Message#$type
1659
- * @type {!ProtoBuf.Reflect.Message}
1660
- * @expose
1733
+ * @alias ProtoBuf.Builder.Message.prototype
1734
+ * @inner
1661
1735
  */
1662
-
1663
- // Extends ProtoBuf.Builder.Message
1664
- Message.prototype = Object.create(ProtoBuf.Builder.Message.prototype);
1736
+ var MessagePrototype = Message.prototype = Object.create(ProtoBuf.Builder.Message.prototype);
1665
1737
 
1666
1738
  /**
1667
1739
  * Adds a value to a repeated field.
@@ -1673,14 +1745,16 @@
1673
1745
  * @throws {Error} If the value cannot be added
1674
1746
  * @expose
1675
1747
  */
1676
- Message.prototype.add = function(key, value, noAssert) {
1677
- var field = T.getChild(key);
1678
- if (!field)
1679
- throw Error(this+"#"+key+" is undefined");
1680
- if (!(field instanceof ProtoBuf.Reflect.Message.Field))
1681
- throw Error(this+"#"+key+" is not a field: "+field.toString(true)); // May throw if it's an enum or embedded message
1682
- if (!field.repeated)
1683
- throw Error(this+"#"+key+" is not a repeated field");
1748
+ MessagePrototype.add = function(key, value, noAssert) {
1749
+ var field = T._fieldsByName[key];
1750
+ if (!noAssert) {
1751
+ if (!field)
1752
+ throw Error(this+"#"+key+" is undefined");
1753
+ if (!(field instanceof ProtoBuf.Reflect.Message.Field))
1754
+ throw Error(this+"#"+key+" is not a field: "+field.toString(true)); // May throw if it's an enum or embedded message
1755
+ if (!field.repeated)
1756
+ throw Error(this+"#"+key+" is not a repeated field");
1757
+ }
1684
1758
  if (this[field.name] === null)
1685
1759
  this[field.name] = [];
1686
1760
  this[field.name].push(noAssert ? value : field.verifyValue(value, true));
@@ -1696,7 +1770,7 @@
1696
1770
  * @throws {Error} If the value cannot be added
1697
1771
  * @expose
1698
1772
  */
1699
- Message.prototype.$add = Message.prototype.add;
1773
+ MessagePrototype.$add = MessagePrototype.add;
1700
1774
 
1701
1775
  /**
1702
1776
  * Sets a field's value.
@@ -1709,23 +1783,31 @@
1709
1783
  * @throws {Error} If the value cannot be set
1710
1784
  * @expose
1711
1785
  */
1712
- Message.prototype.set = function(key, value, noAssert) {
1786
+ MessagePrototype.set = function(key, value, noAssert) {
1713
1787
  if (key && typeof key === 'object') {
1714
1788
  for (var i in key)
1715
1789
  if (key.hasOwnProperty(i))
1716
1790
  this.$set(i, key[i], noAssert);
1717
1791
  return this;
1718
1792
  }
1719
- if (noAssert) {
1720
- this[key] = value;
1721
- return this;
1793
+ var field = T._fieldsByName[key];
1794
+ if (!noAssert) {
1795
+ if (!field)
1796
+ throw Error(this+"#"+key+" is not a field: undefined");
1797
+ if (!(field instanceof ProtoBuf.Reflect.Message.Field))
1798
+ throw Error(this+"#"+key+" is not a field: "+field.toString(true));
1799
+ this[field.name] = (value = field.verifyValue(value)); // May throw
1800
+ } else {
1801
+ this[field.name] = value;
1802
+ }
1803
+ if (field.oneof) {
1804
+ if (value !== null) {
1805
+ if (this[field.oneof.name] !== null)
1806
+ this[this[field.oneof.name]] = null; // Unset the previous (field name is the oneof field's value)
1807
+ this[field.oneof.name] = field.name;
1808
+ } else if (field.oneof.name === key)
1809
+ this[field.oneof.name] = null;
1722
1810
  }
1723
- var field = T.getChild(key);
1724
- if (!field)
1725
- throw Error(this+"#"+key+" is not a field: undefined");
1726
- if (!(field instanceof ProtoBuf.Reflect.Message.Field))
1727
- throw Error(this+"#"+key+" is not a field: "+field.toString(true));
1728
- this[field.name] = field.verifyValue(value); // May throw
1729
1811
  return this;
1730
1812
  };
1731
1813
 
@@ -1735,26 +1817,26 @@
1735
1817
  * @function
1736
1818
  * @param {string} key Key
1737
1819
  * @param {*} value Value to set
1738
- * @param {boolean=} noAssert Whether to assert the value or not (asserts by default)
1820
+ * @param {boolean=} noAssert Whether to not assert the value, defaults to `false`
1739
1821
  * @throws {Error} If the value cannot be set
1740
1822
  * @expose
1741
1823
  */
1742
- Message.prototype.$set = Message.prototype.set;
1824
+ MessagePrototype.$set = MessagePrototype.set;
1743
1825
 
1744
1826
  /**
1745
1827
  * Gets a field's value.
1746
1828
  * @name ProtoBuf.Builder.Message#get
1747
1829
  * @function
1748
1830
  * @param {string} key Key
1749
- * @param {boolean=} noAssert Whether to no assert for an actual field, defaults to `false`
1831
+ * @param {boolean=} noAssert Whether to not assert for an actual field, defaults to `false`
1750
1832
  * @return {*} Value
1751
1833
  * @throws {Error} If there is no such field
1752
1834
  * @expose
1753
1835
  */
1754
- Message.prototype.get = function(key, noAssert) {
1836
+ MessagePrototype.get = function(key, noAssert) {
1755
1837
  if (noAssert)
1756
1838
  return this[key];
1757
- var field = T.getChild(key);
1839
+ var field = T._fieldsByName[key];
1758
1840
  if (!field || !(field instanceof ProtoBuf.Reflect.Message.Field))
1759
1841
  throw Error(this+"#"+key+" is not a field: undefined");
1760
1842
  if (!(field instanceof ProtoBuf.Reflect.Message.Field))
@@ -1771,7 +1853,7 @@
1771
1853
  * @throws {Error} If there is no such field
1772
1854
  * @expose
1773
1855
  */
1774
- Message.prototype.$get = Message.prototype.get;
1856
+ MessagePrototype.$get = MessagePrototype.get;
1775
1857
 
1776
1858
  // Getters and setters
1777
1859
 
@@ -1781,72 +1863,91 @@
1781
1863
  if (field instanceof ProtoBuf.Reflect.Message.ExtensionField)
1782
1864
  continue;
1783
1865
 
1784
- if (ProtoBuf.populateAccessors)
1866
+ if (T.builder.options['populateAccessors'])
1785
1867
  (function(field) {
1786
1868
  // set/get[SomeValue]
1787
1869
  var Name = field.originalName.replace(/(_[a-zA-Z])/g, function(match) {
1788
1870
  return match.toUpperCase().replace('_','');
1789
1871
  });
1790
- Name = Name.substring(0,1).toUpperCase()+Name.substring(1);
1872
+ Name = Name.substring(0,1).toUpperCase() + Name.substring(1);
1791
1873
 
1792
- // set/get_[some_value]
1874
+ // set/get_[some_value] FIXME: Do we really need these?
1793
1875
  var name = field.originalName.replace(/([A-Z])/g, function(match) {
1794
1876
  return "_"+match;
1795
1877
  });
1796
1878
 
1879
+ /**
1880
+ * The current field's unbound setter function.
1881
+ * @function
1882
+ * @param {*} value
1883
+ * @param {boolean=} noAssert
1884
+ * @returns {!ProtoBuf.Builder.Message}
1885
+ * @inner
1886
+ */
1887
+ var setter = function(value, noAssert) {
1888
+ this[field.name] = noAssert ? value : field.verifyValue(value);
1889
+ return this;
1890
+ };
1891
+
1892
+ /**
1893
+ * The current field's unbound getter function.
1894
+ * @function
1895
+ * @returns {*}
1896
+ * @inner
1897
+ */
1898
+ var getter = function() {
1899
+ return this[field.name];
1900
+ };
1901
+
1797
1902
  /**
1798
1903
  * Sets a value. This method is present for each field, but only if there is no name conflict with
1799
- * another field.
1904
+ * another field.
1800
1905
  * @name ProtoBuf.Builder.Message#set[SomeField]
1801
1906
  * @function
1802
1907
  * @param {*} value Value to set
1908
+ * @param {boolean=} noAssert Whether to not assert the value, defaults to `false`
1909
+ * @returns {!ProtoBuf.Builder.Message} this
1803
1910
  * @abstract
1804
1911
  * @throws {Error} If the value cannot be set
1805
1912
  */
1806
1913
  if (T.getChild("set"+Name) === null)
1807
- Message.prototype["set"+Name] = function(value) {
1808
- this.$set(field.name, value);
1809
- };
1914
+ MessagePrototype["set"+Name] = setter;
1810
1915
 
1811
1916
  /**
1812
1917
  * Sets a value. This method is present for each field, but only if there is no name conflict with
1813
- * another field.
1918
+ * another field.
1814
1919
  * @name ProtoBuf.Builder.Message#set_[some_field]
1815
1920
  * @function
1816
1921
  * @param {*} value Value to set
1922
+ * @param {boolean=} noAssert Whether to not assert the value, defaults to `false`
1923
+ * @returns {!ProtoBuf.Builder.Message} this
1817
1924
  * @abstract
1818
1925
  * @throws {Error} If the value cannot be set
1819
1926
  */
1820
1927
  if (T.getChild("set_"+name) === null)
1821
- Message.prototype["set_"+name] = function(value) {
1822
- this.$set(field.name, value);
1823
- };
1928
+ MessagePrototype["set_"+name] = setter;
1824
1929
 
1825
1930
  /**
1826
1931
  * Gets a value. This method is present for each field, but only if there is no name conflict with
1827
- * another field.
1932
+ * another field.
1828
1933
  * @name ProtoBuf.Builder.Message#get[SomeField]
1829
1934
  * @function
1830
1935
  * @abstract
1831
1936
  * @return {*} The value
1832
1937
  */
1833
1938
  if (T.getChild("get"+Name) === null)
1834
- Message.prototype["get"+Name] = function() {
1835
- return this.$get(field.name); // Does not throw, field exists
1836
- };
1939
+ MessagePrototype["get"+Name] = getter;
1837
1940
 
1838
1941
  /**
1839
1942
  * Gets a value. This method is present for each field, but only if there is no name conflict with
1840
- * another field.
1943
+ * another field.
1841
1944
  * @name ProtoBuf.Builder.Message#get_[some_field]
1842
1945
  * @function
1843
1946
  * @return {*} The value
1844
1947
  * @abstract
1845
1948
  */
1846
1949
  if (T.getChild("get_"+name) === null)
1847
- Message.prototype["get_"+name] = function() {
1848
- return this.$get(field.name); // Does not throw, field exists
1849
- };
1950
+ MessagePrototype["get_"+name] = getter;
1850
1951
 
1851
1952
  })(field);
1852
1953
  }
@@ -1867,7 +1968,7 @@
1867
1968
  * @see ProtoBuf.Builder.Message#encodeHex
1868
1969
  * @see ProtoBuf.Builder.Message#encodeAB
1869
1970
  */
1870
- Message.prototype.encode = function(buffer, noVerify) {
1971
+ MessagePrototype.encode = function(buffer, noVerify) {
1871
1972
  if (typeof buffer === 'boolean')
1872
1973
  noVerify = buffer,
1873
1974
  buffer = undefined;
@@ -1893,7 +1994,7 @@
1893
1994
  * @throws {Error} If the message cannot be calculated or if required fields are missing.
1894
1995
  * @expose
1895
1996
  */
1896
- Message.prototype.calculate = function() {
1997
+ MessagePrototype.calculate = function() {
1897
1998
  return T.calculate(this);
1898
1999
  };
1899
2000
 
@@ -1907,7 +2008,7 @@
1907
2008
  * returns the encoded ByteBuffer in the `encoded` property on the error.
1908
2009
  * @expose
1909
2010
  */
1910
- Message.prototype.encodeDelimited = function(buffer) {
2011
+ MessagePrototype.encodeDelimited = function(buffer) {
1911
2012
  var isNew = false;
1912
2013
  if (!buffer)
1913
2014
  buffer = new ByteBuffer(),
@@ -1928,7 +2029,7 @@
1928
2029
  * returns the encoded ArrayBuffer in the `encoded` property on the error.
1929
2030
  * @expose
1930
2031
  */
1931
- Message.prototype.encodeAB = function() {
2032
+ MessagePrototype.encodeAB = function() {
1932
2033
  try {
1933
2034
  return this.encode().toArrayBuffer();
1934
2035
  } catch (e) {
@@ -1946,7 +2047,7 @@
1946
2047
  * returns the encoded ArrayBuffer in the `encoded` property on the error.
1947
2048
  * @expose
1948
2049
  */
1949
- Message.prototype.toArrayBuffer = Message.prototype.encodeAB;
2050
+ MessagePrototype.toArrayBuffer = MessagePrototype.encodeAB;
1950
2051
 
1951
2052
  /**
1952
2053
  * Directly encodes the message to a node Buffer.
@@ -1957,7 +2058,7 @@
1957
2058
  * missing. The later still returns the encoded node Buffer in the `encoded` property on the error.
1958
2059
  * @expose
1959
2060
  */
1960
- Message.prototype.encodeNB = function() {
2061
+ MessagePrototype.encodeNB = function() {
1961
2062
  try {
1962
2063
  return this.encode().toBuffer();
1963
2064
  } catch (e) {
@@ -1975,7 +2076,7 @@
1975
2076
  * returns the encoded node Buffer in the `encoded` property on the error.
1976
2077
  * @expose
1977
2078
  */
1978
- Message.prototype.toBuffer = Message.prototype.encodeNB;
2079
+ MessagePrototype.toBuffer = MessagePrototype.encodeNB;
1979
2080
 
1980
2081
  /**
1981
2082
  * Directly encodes the message to a base64 encoded string.
@@ -1986,7 +2087,7 @@
1986
2087
  * still returns the encoded base64 string in the `encoded` property on the error.
1987
2088
  * @expose
1988
2089
  */
1989
- Message.prototype.encode64 = function() {
2090
+ MessagePrototype.encode64 = function() {
1990
2091
  try {
1991
2092
  return this.encode().toBase64();
1992
2093
  } catch (e) {
@@ -2004,7 +2105,7 @@
2004
2105
  * returns the encoded base64 string in the `encoded` property on the error.
2005
2106
  * @expose
2006
2107
  */
2007
- Message.prototype.toBase64 = Message.prototype.encode64;
2108
+ MessagePrototype.toBase64 = MessagePrototype.encode64;
2008
2109
 
2009
2110
  /**
2010
2111
  * Directly encodes the message to a hex encoded string.
@@ -2015,7 +2116,7 @@
2015
2116
  * still returns the encoded hex string in the `encoded` property on the error.
2016
2117
  * @expose
2017
2118
  */
2018
- Message.prototype.encodeHex = function() {
2119
+ MessagePrototype.encodeHex = function() {
2019
2120
  try {
2020
2121
  return this.encode().toHex();
2021
2122
  } catch (e) {
@@ -2033,38 +2134,38 @@
2033
2134
  * returns the encoded hex string in the `encoded` property on the error.
2034
2135
  * @expose
2035
2136
  */
2036
- Message.prototype.toHex = Message.prototype.encodeHex;
2137
+ MessagePrototype.toHex = MessagePrototype.encodeHex;
2037
2138
 
2038
2139
  /**
2039
2140
  * Clones a message object to a raw object.
2040
2141
  * @param {*} obj Object to clone
2041
- * @param {boolean} includeBuffers Whether to include native buffer data or not
2142
+ * @param {boolean} includeBinaryAsBase64 Whether to include binary data as base64 strings or not
2042
2143
  * @returns {*} Cloned object
2043
2144
  * @inner
2044
2145
  */
2045
- function cloneRaw(obj, includeBuffers) {
2146
+ function cloneRaw(obj, includeBinaryAsBase64) {
2046
2147
  var clone = {};
2047
2148
  for (var i in obj)
2048
2149
  if (obj.hasOwnProperty(i)) {
2049
2150
  if (obj[i] === null || typeof obj[i] !== 'object')
2050
2151
  clone[i] = obj[i];
2051
2152
  else if (obj[i] instanceof ByteBuffer) {
2052
- if (includeBuffers)
2053
- clone[i] = obj.toBuffer();
2153
+ if (includeBinaryAsBase64)
2154
+ clone[i] = obj[i].toBase64();
2054
2155
  } else // is a non-null object
2055
- clone[i] = cloneRaw(obj[i], includeBuffers);
2156
+ clone[i] = cloneRaw(obj[i], includeBinaryAsBase64);
2056
2157
  }
2057
2158
  return clone;
2058
2159
  }
2059
2160
 
2060
2161
  /**
2061
2162
  * Returns the message's raw payload.
2062
- * @param {boolean=} includeBuffers Whether to include native buffer data or not, defaults to `false`
2163
+ * @param {boolean=} includeBinaryAsBase64 Whether to include binary data as base64 strings or not, defaults to `false`
2063
2164
  * @returns {Object.<string,*>} Raw payload
2064
2165
  * @expose
2065
2166
  */
2066
- Message.prototype.toRaw = function(includeBuffers) {
2067
- return cloneRaw(this, !!includeBuffers);
2167
+ MessagePrototype.toRaw = function(includeBinaryAsBase64) {
2168
+ return cloneRaw(this, !!includeBinaryAsBase64);
2068
2169
  };
2069
2170
 
2070
2171
  /**
@@ -2165,7 +2266,7 @@
2165
2266
  * @return {string} String representation as of ".Fully.Qualified.MessageName"
2166
2267
  * @expose
2167
2268
  */
2168
- Message.prototype.toString = function() {
2269
+ MessagePrototype.toString = function() {
2169
2270
  return T.toString();
2170
2271
  };
2171
2272
 
@@ -2189,7 +2290,7 @@
2189
2290
 
2190
2291
  if (Object.defineProperty)
2191
2292
  Object.defineProperty(Message, '$options', { "value": T.buildOpt() }),
2192
- Object.defineProperty(Message.prototype, "$type", {
2293
+ Object.defineProperty(MessagePrototype, "$type", {
2193
2294
  get: function() { return T; }
2194
2295
  });
2195
2296
 
@@ -2199,20 +2300,20 @@
2199
2300
 
2200
2301
  // Static enums and prototyped sub-messages / cached collections
2201
2302
  this._fields = [];
2202
- this._fieldsById = [];
2303
+ this._fieldsById = {};
2304
+ this._fieldsByName = {};
2203
2305
  for (var i=0, k=this.children.length, child; i<k; i++) {
2204
2306
  child = this.children[i];
2205
2307
  if (child instanceof Enum)
2206
- clazz[child['name']] = child.build();
2308
+ clazz[child.name] = child.build();
2207
2309
  else if (child instanceof Message)
2208
- clazz[child['name']] = child.build();
2310
+ clazz[child.name] = child.build();
2209
2311
  else if (child instanceof Message.Field)
2210
2312
  child.build(),
2211
2313
  this._fields.push(child),
2212
- this._fieldsById[child.id] = child;
2213
- else if (child instanceof Extension) {
2214
- // Ignore
2215
- } else
2314
+ this._fieldsById[child.id] = child,
2315
+ this._fieldsByName[child.name] = child;
2316
+ else if (!(child instanceof Message.OneOf) && !(child instanceof Extension)) // Not built
2216
2317
  throw Error("Illegal reflect child of "+this.toString(true)+": "+children[i].toString(true));
2217
2318
  }
2218
2319
 
@@ -2228,11 +2329,11 @@
2228
2329
  * @throws {Error} If required fields are missing or the message cannot be encoded for another reason
2229
2330
  * @expose
2230
2331
  */
2231
- Message.prototype.encode = function(message, buffer, noVerify) {
2332
+ MessagePrototype.encode = function(message, buffer, noVerify) {
2232
2333
  var fieldMissing = null,
2233
2334
  field;
2234
2335
  for (var i=0, k=this._fields.length, val; i<k; ++i) {
2235
- field = this.children[i];
2336
+ field = this._fields[i];
2236
2337
  val = message[field.name];
2237
2338
  if (field.required && val === null) {
2238
2339
  if (fieldMissing === null)
@@ -2255,7 +2356,7 @@
2255
2356
  * @throws {Error} If required fields are missing or the message cannot be calculated for another reason
2256
2357
  * @expose
2257
2358
  */
2258
- Message.prototype.calculate = function(message) {
2359
+ MessagePrototype.calculate = function(message) {
2259
2360
  for (var n=0, i=0, k=this._fields.length, field, val; i<k; ++i) {
2260
2361
  field = this._fields[i];
2261
2362
  val = message[field.name];
@@ -2317,7 +2418,7 @@
2317
2418
  * @throws {Error} If the message cannot be decoded
2318
2419
  * @expose
2319
2420
  */
2320
- Message.prototype.decode = function(buffer, length, expectedGroupEndId) {
2421
+ MessagePrototype.decode = function(buffer, length, expectedGroupEndId) {
2321
2422
  length = typeof length === 'number' ? length : -1;
2322
2423
  var start = buffer.offset,
2323
2424
  msg = new (this.clazz)(),
@@ -2357,8 +2458,14 @@
2357
2458
  }
2358
2459
  if (field.repeated && !field.options["packed"])
2359
2460
  msg[field.name].push(field.decode(wireType, buffer));
2360
- else
2461
+ else {
2361
2462
  msg[field.name] = field.decode(wireType, buffer);
2463
+ if (field.oneof) {
2464
+ if (this[field.oneof.name] !== null)
2465
+ this[this[field.oneof.name]] = null;
2466
+ msg[field.oneof.name] = field.name;
2467
+ }
2468
+ }
2362
2469
  }
2363
2470
 
2364
2471
  // Check if all required fields are present and set default values for optional fields that are not
@@ -2384,17 +2491,19 @@
2384
2491
  /**
2385
2492
  * Constructs a new Message Field.
2386
2493
  * @exports ProtoBuf.Reflect.Message.Field
2387
- * @param {ProtoBuf.Reflect.Message} message Message reference
2494
+ * @param {!ProtoBuf.Builder} builder Builder reference
2495
+ * @param {!ProtoBuf.Reflect.Message} message Message reference
2388
2496
  * @param {string} rule Rule, one of requried, optional, repeated
2389
2497
  * @param {string} type Data type, e.g. int32
2390
2498
  * @param {string} name Field name
2391
2499
  * @param {number} id Unique field id
2392
2500
  * @param {Object.<string,*>=} options Options
2501
+ * @param {!ProtoBuf.Reflect.Message.OneOf=} oneof Enclosing OneOf
2393
2502
  * @constructor
2394
2503
  * @extends ProtoBuf.Reflect.T
2395
2504
  */
2396
- var Field = function(message, rule, type, name, id, options) {
2397
- T.call(this, message, name);
2505
+ var Field = function(builder, message, rule, type, name, id, options, oneof) {
2506
+ T.call(this, builder, message, name);
2398
2507
 
2399
2508
  /**
2400
2509
  * @override
@@ -2451,6 +2560,13 @@
2451
2560
  */
2452
2561
  this.defaultValue = null;
2453
2562
 
2563
+ /**
2564
+ * Enclosing OneOf.
2565
+ * @type {?ProtoBuf.Reflect.Message.OneOf}
2566
+ * @expose
2567
+ */
2568
+ this.oneof = oneof || null;
2569
+
2454
2570
  /**
2455
2571
  * Original field name.
2456
2572
  * @type {string}
@@ -2459,22 +2575,34 @@
2459
2575
  this.originalName = this.name; // Used to revert camelcase transformation on naming collisions
2460
2576
 
2461
2577
  // Convert field names to camel case notation if the override is set
2462
- if (ProtoBuf.convertFieldsToCamelCase && !(this instanceof Message.ExtensionField)) {
2463
- this.name = this.name.replace(/_([a-zA-Z])/g, function($0, $1) {
2464
- return $1.toUpperCase();
2465
- });
2466
- }
2578
+ if (this.builder.options['convertFieldsToCamelCase'] && !(this instanceof Message.ExtensionField))
2579
+ this.name = Field._toCamelCase(this.name);
2467
2580
  };
2468
2581
 
2469
- // Extends T
2470
- Field.prototype = Object.create(T.prototype);
2582
+ /**
2583
+ * Converts a field name to camel case.
2584
+ * @param {string} name Likely underscore notated name
2585
+ * @returns {string} Camel case notated name
2586
+ * @private
2587
+ */
2588
+ Field._toCamelCase = function(name) {
2589
+ return name.replace(/_([a-zA-Z])/g, function($0, $1) {
2590
+ return $1.toUpperCase();
2591
+ });
2592
+ };
2593
+
2594
+ /**
2595
+ * @alias ProtoBuf.Reflect.Message.Field.prototype
2596
+ * @inner
2597
+ */
2598
+ var FieldPrototype = Field.prototype = Object.create(T.prototype);
2471
2599
 
2472
2600
  /**
2473
2601
  * Builds the field.
2474
2602
  * @override
2475
2603
  * @expose
2476
2604
  */
2477
- Field.prototype.build = function() {
2605
+ FieldPrototype.build = function() {
2478
2606
  this.defaultValue = typeof this.options['default'] !== 'undefined'
2479
2607
  ? this.verifyValue(this.options['default']) : null;
2480
2608
  };
@@ -2507,7 +2635,7 @@
2507
2635
  * @throws {Error} If the value cannot be set for this field
2508
2636
  * @expose
2509
2637
  */
2510
- Field.prototype.verifyValue = function(value, skipRepeated) {
2638
+ FieldPrototype.verifyValue = function(value, skipRepeated) {
2511
2639
  skipRepeated = skipRepeated || false;
2512
2640
  var fail = function(val, msg) {
2513
2641
  throw Error("Illegal value for "+this.toString(true)+" of type "+this.type.name+": "+val+" ("+msg+")");
@@ -2595,20 +2723,18 @@
2595
2723
 
2596
2724
  // Length-delimited bytes
2597
2725
  case ProtoBuf.TYPES["bytes"]:
2598
- return value && value instanceof ByteBuffer
2599
- ? value
2600
- : ByteBuffer.wrap(value);
2726
+ if (ByteBuffer.isByteBuffer(value))
2727
+ return value;
2728
+ return ByteBuffer.wrap(value, "base64");
2601
2729
 
2602
2730
  // Constant enum value
2603
2731
  case ProtoBuf.TYPES["enum"]: {
2604
2732
  var values = this.resolvedType.getChildren(Enum.Value);
2605
- for (i=0; i<values.length; i++) {
2606
- if (values[i].name == value) {
2733
+ for (i=0; i<values.length; i++)
2734
+ if (values[i].name == value)
2607
2735
  return values[i].id;
2608
- } else if (values[i].id == value) {
2736
+ else if (values[i].id == value)
2609
2737
  return values[i].id;
2610
- }
2611
- }
2612
2738
  fail(value, "not a valid enum value");
2613
2739
  }
2614
2740
  // Embedded message
@@ -2643,7 +2769,7 @@
2643
2769
  * @throws {Error} If the field cannot be encoded
2644
2770
  * @expose
2645
2771
  */
2646
- Field.prototype.encode = function(value, buffer) {
2772
+ FieldPrototype.encode = function(value, buffer) {
2647
2773
  if (this.type === null || typeof this.type !== 'object')
2648
2774
  throw Error("[INTERNAL] Unresolved type in "+this.toString(true)+": "+this.type);
2649
2775
  if (value === null || (this.repeated && value.length == 0))
@@ -2695,7 +2821,7 @@
2695
2821
  * @throws {Error} If the value cannot be encoded
2696
2822
  * @expose
2697
2823
  */
2698
- Field.prototype.encodeValue = function(value, buffer) {
2824
+ FieldPrototype.encodeValue = function(value, buffer) {
2699
2825
  if (value === null) return buffer; // Nothing to encode
2700
2826
  // Tag has already been written
2701
2827
 
@@ -2816,7 +2942,7 @@
2816
2942
  * @returns {number} Byte length
2817
2943
  * @expose
2818
2944
  */
2819
- Field.prototype.calculate = function(value) {
2945
+ FieldPrototype.calculate = function(value) {
2820
2946
  value = this.verifyValue(value); // May throw
2821
2947
  if (this.type === null || typeof this.type !== 'object')
2822
2948
  throw Error("[INTERNAL] Unresolved type in "+this.toString(true)+": "+this.type);
@@ -2855,7 +2981,7 @@
2855
2981
  * @throws {Error} If the value cannot be calculated
2856
2982
  * @expose
2857
2983
  */
2858
- Field.prototype.calculateValue = function(value) {
2984
+ FieldPrototype.calculateValue = function(value) {
2859
2985
  if (value === null) return 0; // Nothing to encode
2860
2986
  // Tag has already been written
2861
2987
  var n;
@@ -2911,7 +3037,7 @@
2911
3037
  * @throws {Error} If the field cannot be decoded
2912
3038
  * @expose
2913
3039
  */
2914
- Field.prototype.decode = function(wireType, buffer, skipRepeated) {
3040
+ FieldPrototype.decode = function(wireType, buffer, skipRepeated) {
2915
3041
  var value, nBytes;
2916
3042
  if (wireType != this.type.wireType && (skipRepeated || (wireType != ProtoBuf.WIRE_TYPES.LDELIM || !this.repeated)))
2917
3043
  throw Error("Illegal wire type for field "+this.toString(true)+": "+wireType+" ("+this.type.wireType+" expected)");
@@ -3011,7 +3137,7 @@
3011
3137
 
3012
3138
  // We should never end here
3013
3139
  throw Error("[INTERNAL] Illegal wire type for "+this.toString(true)+": "+wireType);
3014
- }
3140
+ };
3015
3141
 
3016
3142
  /**
3017
3143
  * @alias ProtoBuf.Reflect.Message.Field
@@ -3022,7 +3148,8 @@
3022
3148
  /**
3023
3149
  * Constructs a new Message ExtensionField.
3024
3150
  * @exports ProtoBuf.Reflect.Message.ExtensionField
3025
- * @param {ProtoBuf.Reflect.Message} message Message reference
3151
+ * @param {!ProtoBuf.Builder} builder Builder reference
3152
+ * @param {!ProtoBuf.Reflect.Message} message Message reference
3026
3153
  * @param {string} rule Rule, one of requried, optional, repeated
3027
3154
  * @param {string} type Data type, e.g. int32
3028
3155
  * @param {string} name Field name
@@ -3031,8 +3158,8 @@
3031
3158
  * @constructor
3032
3159
  * @extends ProtoBuf.Reflect.Message.Field
3033
3160
  */
3034
- var ExtensionField = function(message, rule, type, name, id, options) {
3035
- Field.call(this, message, rule, type, name, id, options);
3161
+ var ExtensionField = function(builder, message, rule, type, name, id, options) {
3162
+ Field.call(this, builder, message, rule, type, name, id, options);
3036
3163
 
3037
3164
  /**
3038
3165
  * Extension reference.
@@ -3051,17 +3178,44 @@
3051
3178
  */
3052
3179
  Reflect.Message.ExtensionField = ExtensionField;
3053
3180
 
3181
+ /**
3182
+ * Constructs a new Message OneOf.
3183
+ * @exports ProtoBuf.Reflect.Message.OneOf
3184
+ * @param {!ProtoBuf.Builder} builder Builder reference
3185
+ * @param {!ProtoBuf.Reflect.Message} message Message reference
3186
+ * @param {string} name OneOf name
3187
+ * @constructor
3188
+ * @extends ProtoBuf.Reflect.T
3189
+ */
3190
+ var OneOf = function(builder, message, name) {
3191
+ T.call(this, builder, message, name);
3192
+
3193
+ /**
3194
+ * Enclosed fields.
3195
+ * @type {!Array.<!ProtoBuf.Reflect.Message.Field>}
3196
+ * @expose
3197
+ */
3198
+ this.fields = [];
3199
+ };
3200
+
3201
+ /**
3202
+ * @alias ProtoBuf.Reflect.Message.OneOf
3203
+ * @expose
3204
+ */
3205
+ Reflect.Message.OneOf = OneOf;
3206
+
3054
3207
  /**
3055
3208
  * Constructs a new Enum.
3056
3209
  * @exports ProtoBuf.Reflect.Enum
3210
+ * @param {!ProtoBuf.Builder} builder Builder reference
3057
3211
  * @param {!ProtoBuf.Reflect.T} parent Parent Reflect object
3058
3212
  * @param {string} name Enum name
3059
3213
  * @param {Object.<string,*>=} options Enum options
3060
3214
  * @constructor
3061
3215
  * @extends ProtoBuf.Reflect.Namespace
3062
3216
  */
3063
- var Enum = function(parent, name, options) {
3064
- Namespace.call(this, parent, name, options);
3217
+ var Enum = function(builder, parent, name, options) {
3218
+ Namespace.call(this, builder, parent, name, options);
3065
3219
 
3066
3220
  /**
3067
3221
  * @override
@@ -3076,15 +3230,18 @@
3076
3230
  this.object = null;
3077
3231
  };
3078
3232
 
3079
- // Extends Namespace
3080
- Enum.prototype = Object.create(Namespace.prototype);
3233
+ /**
3234
+ * @alias ProtoBuf.Reflect.Enum.prototype
3235
+ * @inner
3236
+ */
3237
+ var EnumPrototype = Enum.prototype = Object.create(Namespace.prototype);
3081
3238
 
3082
3239
  /**
3083
3240
  * Builds this enum and returns the runtime counterpart.
3084
3241
  * @return {Object<string,*>}
3085
3242
  * @expose
3086
3243
  */
3087
- Enum.prototype.build = function() {
3244
+ EnumPrototype.build = function() {
3088
3245
  var enm = {},
3089
3246
  values = this.getChildren(Enum.Value);
3090
3247
  for (var i=0, k=values.length; i<k; ++i)
@@ -3103,14 +3260,15 @@
3103
3260
  /**
3104
3261
  * Constructs a new Enum Value.
3105
3262
  * @exports ProtoBuf.Reflect.Enum.Value
3263
+ * @param {!ProtoBuf.Builder} builder Builder reference
3106
3264
  * @param {!ProtoBuf.Reflect.Enum} enm Enum reference
3107
3265
  * @param {string} name Field name
3108
3266
  * @param {number} id Unique field id
3109
3267
  * @constructor
3110
3268
  * @extends ProtoBuf.Reflect.T
3111
3269
  */
3112
- var Value = function(enm, name, id) {
3113
- T.call(this, enm, name);
3270
+ var Value = function(builder, enm, name, id) {
3271
+ T.call(this, builder, enm, name);
3114
3272
 
3115
3273
  /**
3116
3274
  * @override
@@ -3138,12 +3296,13 @@
3138
3296
  * An extension (field).
3139
3297
  * @exports ProtoBuf.Reflect.Extension
3140
3298
  * @constructor
3141
- * @param {ProtoBuf.Reflect.T} parent Parent object
3299
+ * @param {!ProtoBuf.Builder} builder Builder reference
3300
+ * @param {!ProtoBuf.Reflect.T} parent Parent object
3142
3301
  * @param {string} name Object name
3143
3302
  * @param {!ProtoBuf.Reflect.Message.Field} field Extension field
3144
3303
  */
3145
- var Extension = function(parent, name, field) {
3146
- T.call(this, parent, name);
3304
+ var Extension = function(builder, parent, name, field) {
3305
+ T.call(this, builder, parent, name);
3147
3306
 
3148
3307
  /**
3149
3308
  * Extended message field.
@@ -3165,14 +3324,15 @@
3165
3324
  /**
3166
3325
  * Constructs a new Service.
3167
3326
  * @exports ProtoBuf.Reflect.Service
3327
+ * @param {!ProtoBuf.Builder} builder Builder reference
3168
3328
  * @param {!ProtoBuf.Reflect.Namespace} root Root
3169
3329
  * @param {string} name Service name
3170
3330
  * @param {Object.<string,*>=} options Options
3171
3331
  * @constructor
3172
3332
  * @extends ProtoBuf.Reflect.Namespace
3173
3333
  */
3174
- var Service = function(root, name, options) {
3175
- Namespace.call(this, root, name, options);
3334
+ var Service = function(builder, root, name, options) {
3335
+ Namespace.call(this, builder, root, name, options);
3176
3336
 
3177
3337
  /**
3178
3338
  * @override
@@ -3186,8 +3346,11 @@
3186
3346
  this.clazz = null;
3187
3347
  };
3188
3348
 
3189
- // Extends Namespace
3190
- Service.prototype = Object.create(Namespace.prototype);
3349
+ /**
3350
+ * @alias ProtoBuf.Reflect.Service.prototype
3351
+ * @inner
3352
+ */
3353
+ var ServicePrototype = Service.prototype = Object.create(Namespace.prototype);
3191
3354
 
3192
3355
  /**
3193
3356
  * Builds the service and returns the runtime counterpart, which is a fully functional class.
@@ -3197,7 +3360,7 @@
3197
3360
  * @throws {Error} If the message cannot be built
3198
3361
  * @expose
3199
3362
  */
3200
- Service.prototype.build = function(rebuild) {
3363
+ ServicePrototype.build = function(rebuild) {
3201
3364
  if (this.clazz && !rebuild)
3202
3365
  return this.clazz;
3203
3366
 
@@ -3229,12 +3392,15 @@
3229
3392
  };
3230
3393
  };
3231
3394
 
3232
- // Extends ProtoBuf.Builder.Service
3233
- Service.prototype = Object.create(ProtoBuf.Builder.Service.prototype);
3395
+ /**
3396
+ * @alias ProtoBuf.Builder.Service.prototype
3397
+ * @inner
3398
+ */
3399
+ var ServicePrototype = Service.prototype = Object.create(ProtoBuf.Builder.Service.prototype);
3234
3400
 
3235
3401
  if (Object.defineProperty)
3236
3402
  Object.defineProperty(Service, "$options", { "value": T.buildOpt() }),
3237
- Object.defineProperty(Service.prototype, "$options", { "value": Service["$options"] });
3403
+ Object.defineProperty(ServicePrototype, "$options", { "value": Service["$options"] });
3238
3404
 
3239
3405
  /**
3240
3406
  * Asynchronously performs an RPC call using the given RPC implementation.
@@ -3262,7 +3428,7 @@
3262
3428
  (function(method) {
3263
3429
 
3264
3430
  // service#Method(message, callback)
3265
- Service.prototype[method.name] = function(req, callback) {
3431
+ ServicePrototype[method.name] = function(req, callback) {
3266
3432
  try {
3267
3433
  if (!req || !(req instanceof method.resolvedRequestType.clazz)) {
3268
3434
  setTimeout(callback.bind(this, Error("Illegal request type provided to service method "+T.name+"#"+method.name)), 0);
@@ -3292,7 +3458,7 @@
3292
3458
 
3293
3459
  if (Object.defineProperty)
3294
3460
  Object.defineProperty(Service[method.name], "$options", { "value": method.buildOpt() }),
3295
- Object.defineProperty(Service.prototype[method.name], "$options", { "value": Service[method.name]["$options"] });
3461
+ Object.defineProperty(ServicePrototype[method.name], "$options", { "value": Service[method.name]["$options"] });
3296
3462
  })(rpc[i]);
3297
3463
  }
3298
3464
 
@@ -3310,14 +3476,15 @@
3310
3476
  /**
3311
3477
  * Abstract service method.
3312
3478
  * @exports ProtoBuf.Reflect.Service.Method
3479
+ * @param {!ProtoBuf.Builder} builder Builder reference
3313
3480
  * @param {!ProtoBuf.Reflect.Service} svc Service
3314
3481
  * @param {string} name Method name
3315
3482
  * @param {Object.<string,*>=} options Options
3316
3483
  * @constructor
3317
3484
  * @extends ProtoBuf.Reflect.T
3318
3485
  */
3319
- var Method = function(svc, name, options) {
3320
- T.call(this, svc, name);
3486
+ var Method = function(builder, svc, name, options) {
3487
+ T.call(this, builder, svc, name);
3321
3488
 
3322
3489
  /**
3323
3490
  * @override
@@ -3332,8 +3499,11 @@
3332
3499
  this.options = options || {};
3333
3500
  };
3334
3501
 
3335
- // Extends T
3336
- Method.prototype = Object.create(T.prototype);
3502
+ /**
3503
+ * @alias ProtoBuf.Reflect.Service.Method.prototype
3504
+ * @inner
3505
+ */
3506
+ var MethodPrototype = Method.prototype = Object.create(T.prototype);
3337
3507
 
3338
3508
  /**
3339
3509
  * Builds the method's '$options' property.
@@ -3341,7 +3511,7 @@
3341
3511
  * @function
3342
3512
  * @return {Object.<string,*>}
3343
3513
  */
3344
- Method.prototype.buildOpt = Namespace.prototype.buildOpt;
3514
+ MethodPrototype.buildOpt = NamespacePrototype.buildOpt;
3345
3515
 
3346
3516
  /**
3347
3517
  * @alias ProtoBuf.Reflect.Service.Method
@@ -3352,6 +3522,7 @@
3352
3522
  /**
3353
3523
  * RPC service method.
3354
3524
  * @exports ProtoBuf.Reflect.Service.RPCMethod
3525
+ * @param {!ProtoBuf.Builder} builder Builder reference
3355
3526
  * @param {!ProtoBuf.Reflect.Service} svc Service
3356
3527
  * @param {string} name Method name
3357
3528
  * @param {string} request Request message name
@@ -3360,8 +3531,8 @@
3360
3531
  * @constructor
3361
3532
  * @extends ProtoBuf.Reflect.Service.Method
3362
3533
  */
3363
- var RPCMethod = function(svc, name, request, response, options) {
3364
- Method.call(this, svc, name, options);
3534
+ var RPCMethod = function(builder, svc, name, request, response, options) {
3535
+ Method.call(this, builder, svc, name, options);
3365
3536
 
3366
3537
  /**
3367
3538
  * @override
@@ -3407,6 +3578,7 @@
3407
3578
  Reflect.Service.RPCMethod = RPCMethod;
3408
3579
 
3409
3580
  return Reflect;
3581
+
3410
3582
  })(ProtoBuf);
3411
3583
 
3412
3584
  /**
@@ -3420,16 +3592,17 @@
3420
3592
  * Constructs a new Builder.
3421
3593
  * @exports ProtoBuf.Builder
3422
3594
  * @class Provides the functionality to build protocol messages.
3595
+ * @param {Object.<string,*>=} options Options
3423
3596
  * @constructor
3424
3597
  */
3425
- var Builder = function() {
3598
+ var Builder = function(options) {
3426
3599
 
3427
3600
  /**
3428
3601
  * Namespace.
3429
3602
  * @type {ProtoBuf.Reflect.Namespace}
3430
3603
  * @expose
3431
3604
  */
3432
- this.ns = new Reflect.Namespace(null, ""); // Global namespace
3605
+ this.ns = new Reflect.Namespace(this, null, ""); // Global namespace
3433
3606
 
3434
3607
  /**
3435
3608
  * Namespace pointer.
@@ -3465,13 +3638,26 @@
3465
3638
  * @expose
3466
3639
  */
3467
3640
  this.importRoot = null;
3641
+
3642
+ /**
3643
+ * Options.
3644
+ * @type {!Object.<string, *>}
3645
+ * @expose
3646
+ */
3647
+ this.options = options || {};
3468
3648
  };
3469
3649
 
3650
+ /**
3651
+ * @alias ProtoBuf.Builder.prototype
3652
+ * @inner
3653
+ */
3654
+ var BuilderPrototype = Builder.prototype;
3655
+
3470
3656
  /**
3471
3657
  * Resets the pointer to the root namespace.
3472
3658
  * @expose
3473
3659
  */
3474
- Builder.prototype.reset = function() {
3660
+ BuilderPrototype.reset = function() {
3475
3661
  this.ptr = this.ns;
3476
3662
  };
3477
3663
 
@@ -3483,7 +3669,7 @@
3483
3669
  * @throws {Error} If the package name is invalid
3484
3670
  * @expose
3485
3671
  */
3486
- Builder.prototype.define = function(pkg, options) {
3672
+ BuilderPrototype.define = function(pkg, options) {
3487
3673
  if (typeof pkg !== 'string' || !Lang.TYPEREF.test(pkg))
3488
3674
  throw Error("Illegal package: "+pkg);
3489
3675
  var part = pkg.split("."), i;
@@ -3492,7 +3678,7 @@
3492
3678
  throw Error("Illegal package: "+part[i]);
3493
3679
  for (i=0; i<part.length; i++) {
3494
3680
  if (this.ptr.getChild(part[i]) === null) // Keep existing namespace
3495
- this.ptr.addChild(new Reflect.Namespace(this.ptr, part[i], options));
3681
+ this.ptr.addChild(new Reflect.Namespace(this, this.ptr, part[i], options));
3496
3682
  this.ptr = this.ptr.getChild(part[i]);
3497
3683
  }
3498
3684
  return this;
@@ -3606,7 +3792,7 @@
3606
3792
  * @throws {Error} If a message definition is invalid
3607
3793
  * @expose
3608
3794
  */
3609
- Builder.prototype.create = function(defs) {
3795
+ BuilderPrototype.create = function(defs) {
3610
3796
  if (!defs)
3611
3797
  return this; // Nothing to create
3612
3798
  if (!ProtoBuf.Util.isArray(defs))
@@ -3615,35 +3801,51 @@
3615
3801
  return this;
3616
3802
 
3617
3803
  // It's quite hard to keep track of scopes and memory here, so let's do this iteratively.
3618
- var stack = [], def, obj, subObj, i, j;
3804
+ var stack = [];
3619
3805
  stack.push(defs); // One level [a, b, c]
3620
3806
  while (stack.length > 0) {
3621
3807
  defs = stack.pop();
3622
3808
  if (ProtoBuf.Util.isArray(defs)) { // Stack always contains entire namespaces
3623
3809
  while (defs.length > 0) {
3624
- def = defs.shift(); // Namespace always contains an array of messages, enums and services
3810
+ var def = defs.shift(); // Namespace always contains an array of messages, enums and services
3625
3811
  if (Builder.isValidMessage(def)) {
3626
- obj = new Reflect.Message(this.ptr, def["name"], def["options"], def["isGroup"]);
3812
+ var obj = new Reflect.Message(this, this.ptr, def["name"], def["options"], def["isGroup"]);
3813
+ // Create OneOfs
3814
+ var oneofs = {};
3815
+ if (def["oneofs"]) {
3816
+ var keys = Object.keys(def["oneofs"]);
3817
+ for (var i=0, k=keys.length; i<k; ++i)
3818
+ obj.addChild(oneofs[keys[i]] = new Reflect.Message.OneOf(this, obj, keys[i]));
3819
+ }
3627
3820
  // Create fields
3628
3821
  if (def["fields"] && def["fields"].length > 0) {
3629
- for (i=0; i<def["fields"].length; i++) { // i=Fields
3630
- if (obj.getChild(def['fields'][i]['id']) !== null)
3631
- throw Error("Duplicate field id in message "+obj.name+": "+def['fields'][i]['id']);
3632
- if (def["fields"][i]["options"]) {
3633
- subObj = Object.keys(def["fields"][i]["options"]);
3634
- for (j=0; j<subObj.length; j++) { // j=Option names
3635
- if (typeof subObj[j] !== 'string')
3636
- throw Error("Illegal field option name in message "+obj.name+"#"+def["fields"][i]["name"]+": "+subObj[j]);
3637
- if (typeof def["fields"][i]["options"][subObj[j]] !== 'string' && typeof def["fields"][i]["options"][subObj[j]] !== 'number' && typeof def["fields"][i]["options"][subObj[j]] !== 'boolean')
3638
- throw Error("Illegal field option value in message "+obj.name+"#"+def["fields"][i]["name"]+"#"+subObj[j]+": "+def["fields"][i]["options"][subObj[j]]);
3822
+ for (i=0, k=def["fields"].length; i<k; ++i) { // i:k=Fields
3823
+ var fld = def['fields'][i];
3824
+ if (obj.getChild(fld['id']) !== null)
3825
+ throw Error("Duplicate field id in message "+obj.name+": "+fld['id']);
3826
+ if (fld["options"]) {
3827
+ var opts = Object.keys(fld["options"]);
3828
+ for (var j= 0,l=opts.length; j<l; ++j) { // j:l=Option names
3829
+ if (typeof opts[j] !== 'string')
3830
+ throw Error("Illegal field option name in message "+obj.name+"#"+fld["name"]+": "+opts[j]);
3831
+ if (typeof fld["options"][opts[j]] !== 'string' && typeof fld["options"][opts[j]] !== 'number' && typeof fld["options"][opts[j]] !== 'boolean')
3832
+ throw Error("Illegal field option value in message "+obj.name+"#"+fld["name"]+"#"+opts[j]+": "+fld["options"][opts[j]]);
3639
3833
  }
3640
- subObj = null;
3641
3834
  }
3642
- obj.addChild(new Reflect.Message.Field(obj, def["fields"][i]["rule"], def["fields"][i]["type"], def["fields"][i]["name"], def["fields"][i]["id"], def["fields"][i]["options"]));
3835
+ var oneof = null;
3836
+ if (typeof fld["oneof"] === 'string') {
3837
+ oneof = oneofs[fld["oneof"]];
3838
+ if (typeof oneof === 'undefined')
3839
+ throw Error("Illegal oneof in message "+obj.name+"#"+fld["name"]+": "+fld["oneof"]);
3840
+ }
3841
+ fld = new Reflect.Message.Field(this, obj, fld["rule"], fld["type"], fld["name"], fld["id"], fld["options"], oneof);
3842
+ if (oneof)
3843
+ oneof.fields.push(fld);
3844
+ obj.addChild(fld);
3643
3845
  }
3644
3846
  }
3645
3847
  // Push enums and messages to stack
3646
- subObj = [];
3848
+ var subObj = [];
3647
3849
  if (typeof def["enums"] !== 'undefined' && def['enums'].length > 0)
3648
3850
  for (i=0; i<def["enums"].length; i++)
3649
3851
  subObj.push(def["enums"][i]);
@@ -3670,16 +3872,16 @@
3670
3872
  subObj = null;
3671
3873
  obj = null;
3672
3874
  } else if (Builder.isValidEnum(def)) {
3673
- obj = new Reflect.Enum(this.ptr, def["name"], def["options"]);
3875
+ obj = new Reflect.Enum(this, this.ptr, def["name"], def["options"]);
3674
3876
  for (i=0; i<def["values"].length; i++)
3675
- obj.addChild(new Reflect.Enum.Value(obj, def["values"][i]["name"], def["values"][i]["id"]));
3877
+ obj.addChild(new Reflect.Enum.Value(this, obj, def["values"][i]["name"], def["values"][i]["id"]));
3676
3878
  this.ptr.addChild(obj);
3677
3879
  obj = null;
3678
3880
  } else if (Builder.isValidService(def)) {
3679
- obj = new Reflect.Service(this.ptr, def["name"], def["options"]);
3881
+ obj = new Reflect.Service(this, this.ptr, def["name"], def["options"]);
3680
3882
  for (i in def["rpc"])
3681
3883
  if (def["rpc"].hasOwnProperty(i))
3682
- obj.addChild(new Reflect.Service.RPCMethod(obj, i, def["rpc"][i]["request"], def["rpc"][i]["response"], def["rpc"][i]["options"]));
3884
+ obj.addChild(new Reflect.Service.RPCMethod(this, obj, i, def["rpc"][i]["request"], def["rpc"][i]["response"], def["rpc"][i]["options"]));
3683
3885
  this.ptr.addChild(obj);
3684
3886
  obj = null;
3685
3887
  } else if (Builder.isValidExtend(def)) {
@@ -3690,10 +3892,16 @@
3690
3892
  throw Error("Duplicate extended field id in message "+obj.name+": "+def['fields'][i]['id']);
3691
3893
  if (def['fields'][i]['id'] < obj.extensions[0] || def['fields'][i]['id'] > obj.extensions[1])
3692
3894
  throw Error("Illegal extended field id in message "+obj.name+": "+def['fields'][i]['id']+" ("+obj.extensions.join(' to ')+" expected)");
3895
+ // Convert extension field names to camel case notation if the override is set
3896
+ var name = def["fields"][i]["name"];
3897
+ if (this.options['convertFieldsToCamelCase'])
3898
+ name = Reflect.Message.Field._toCamelCase(def["fields"][i]["name"]);
3693
3899
  // see #161: Extensions use their fully qualified name as their runtime key and...
3694
- var fld = new Reflect.Message.ExtensionField(obj, def["fields"][i]["rule"], def["fields"][i]["type"], this.ptr.fqn()+'.'+def["fields"][i]["name"], def["fields"][i]["id"], def["fields"][i]["options"]);
3695
- // ...are added on top of the current namespace as an extension which is used for resolving their type later on
3696
- var ext = new Reflect.Extension(this.ptr, def["fields"][i]["name"], fld);
3900
+ fld = new Reflect.Message.ExtensionField(this, obj, def["fields"][i]["rule"], def["fields"][i]["type"], this.ptr.fqn()+'.'+name, def["fields"][i]["id"], def["fields"][i]["options"]);
3901
+ // ...are added on top of the current namespace as an extension which is used for
3902
+ // resolving their type later on (the extension always keeps the original name to
3903
+ // prevent naming collisions)
3904
+ var ext = new Reflect.Extension(this, this.ptr, def["fields"][i]["name"], fld);
3697
3905
  fld.extension = ext;
3698
3906
  this.ptr.addChild(ext);
3699
3907
  obj.addChild(fld);
@@ -3723,7 +3931,7 @@
3723
3931
  * @throws {Error} If the definition or file cannot be imported
3724
3932
  * @expose
3725
3933
  */
3726
- Builder.prototype["import"] = function(json, filename) {
3934
+ BuilderPrototype["import"] = function(json, filename) {
3727
3935
  if (typeof filename === 'string') {
3728
3936
  if (ProtoBuf.Util.IS_NODE)
3729
3937
  filename = require("path")['resolve'](filename);
@@ -3857,7 +4065,7 @@
3857
4065
  * @throws {Error} If a type cannot be resolved
3858
4066
  * @expose
3859
4067
  */
3860
- Builder.prototype.resolveAll = function() {
4068
+ BuilderPrototype.resolveAll = function() {
3861
4069
  // Resolve all reflected objects
3862
4070
  var res;
3863
4071
  if (this.ptr == null || typeof this.ptr.type === 'object')
@@ -3900,9 +4108,7 @@
3900
4108
  // Should not happen as nothing else is implemented
3901
4109
  throw Error("Illegal service type in "+this.ptr.toString(true));
3902
4110
  }
3903
- } else if (this.ptr instanceof ProtoBuf.Reflect.Extension) {
3904
- // There are no runtime counterparts to extensions
3905
- } else
4111
+ } else if (!(this.ptr instanceof ProtoBuf.Reflect.Message.OneOf) && !(this.ptr instanceof ProtoBuf.Reflect.Extension))
3906
4112
  throw Error("Illegal object in namespace: "+typeof(this.ptr)+":"+this.ptr);
3907
4113
  this.reset();
3908
4114
  };
@@ -3915,7 +4121,7 @@
3915
4121
  * @throws {Error} If a type could not be resolved
3916
4122
  * @expose
3917
4123
  */
3918
- Builder.prototype.build = function(path) {
4124
+ BuilderPrototype.build = function(path) {
3919
4125
  this.reset();
3920
4126
  if (!this.resolved)
3921
4127
  this.resolveAll(),
@@ -3944,7 +4150,7 @@
3944
4150
  * @param {string=} path Specifies what to return. If omitted, the entire namespace wiil be returned.
3945
4151
  * @return {ProtoBuf.Reflect.T} Reflection descriptor or `null` if not found
3946
4152
  */
3947
- Builder.prototype.lookup = function(path) {
4153
+ BuilderPrototype.lookup = function(path) {
3948
4154
  return path ? this.ns.resolve(path) : this.ns;
3949
4155
  };
3950
4156
 
@@ -3953,7 +4159,7 @@
3953
4159
  * @return {string} String representation as of "Builder"
3954
4160
  * @expose
3955
4161
  */
3956
- Builder.prototype.toString = function() {
4162
+ BuilderPrototype.toString = function() {
3957
4163
  return "Builder";
3958
4164
  };
3959
4165
 
@@ -3977,10 +4183,9 @@
3977
4183
  * @expose
3978
4184
  */
3979
4185
  ProtoBuf.loadProto = function(proto, builder, filename) {
3980
- if (typeof builder === 'string' || (builder && typeof builder["file"] === 'string' && typeof builder["root"] === 'string')) {
3981
- filename = builder;
3982
- builder = null;
3983
- }
4186
+ if (typeof builder === 'string' || (builder && typeof builder["file"] === 'string' && typeof builder["root"] === 'string'))
4187
+ filename = builder,
4188
+ builder = undefined;
3984
4189
  return ProtoBuf.loadJson((new ProtoBuf.DotProto.Parser(proto)).parse(), builder, filename);
3985
4190
  };
3986
4191
 
@@ -4047,18 +4252,18 @@
4047
4252
 
4048
4253
 
4049
4254
  /**
4050
- * Constructs a new Builder with the specified package defined.
4051
- * @param {string=} pkg Package name as fully qualified name, e.g. "My.Game". If no package is specified, the
4052
- * builder will only contain a global namespace.
4053
- * @param {Object.<string,*>=} options Top level options
4054
- * @return {ProtoBuf.Builder} New Builder
4255
+ * Constructs a new empty Builder.
4256
+ * @param {Object.<string,*>=} options Builder options, defaults to global options set on ProtoBuf
4257
+ * @return {!ProtoBuf.Builder} Builder
4055
4258
  * @expose
4056
4259
  */
4057
- ProtoBuf.newBuilder = function(pkg, options) {
4058
- var builder = new ProtoBuf.Builder();
4059
- if (typeof pkg !== 'undefined' && pkg !== null)
4060
- builder.define(pkg, options);
4061
- return builder;
4260
+ ProtoBuf.newBuilder = function(options) {
4261
+ options = options || {};
4262
+ if (typeof options['convertFieldsToCamelCase'] === 'undefined')
4263
+ options['convertFieldsToCamelCase'] = ProtoBuf.convertFieldsToCamelCase;
4264
+ if (typeof options['populateAccessors'] === 'undefined')
4265
+ options['populateAccessors'] = ProtoBuf.populateAccessors;
4266
+ return new ProtoBuf.Builder(options);
4062
4267
  };
4063
4268
 
4064
4269
  /**
@@ -4080,7 +4285,6 @@
4080
4285
  json = JSON.parse(json);
4081
4286
  builder["import"](json, filename);
4082
4287
  builder.resolveAll();
4083
- builder.build();
4084
4288
  return builder;
4085
4289
  };
4086
4290
 
@@ -4121,8 +4325,8 @@
4121
4325
  return ProtoBuf;
4122
4326
  }
4123
4327
 
4124
- /* CommonJS */ if (typeof module !== 'undefined' && module["exports"])
4125
- module["exports"] = init(require("bytebuffer"));
4328
+ /* CommonJS */ if (typeof require === 'function' && typeof module === 'object' && module && typeof exports === 'object' && exports)
4329
+ module['exports'] = init(require("bytebuffer"));
4126
4330
  /* AMD */ else if (typeof define === 'function' && define["amd"])
4127
4331
  define(["ByteBuffer"], init);
4128
4332
  /* Global */ else