From 1954e348234acdcc23cb08e06d1fb173c6d9e141 Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Wed, 20 Jul 2016 17:48:03 -0700 Subject: WIP. --- js/binary/proto_test.js | 12 +- js/gulpfile.js | 8 +- js/proto3_test.js | 12 +- src/google/protobuf/compiler/js/js_generator.cc | 346 ++++++++++++------------ src/google/protobuf/compiler/js/js_generator.h | 10 +- src/google/protobuf/compiler/main.cc | 5 +- 6 files changed, 201 insertions(+), 192 deletions(-) diff --git a/js/binary/proto_test.js b/js/binary/proto_test.js index 14d0f42e..4a2d797e 100644 --- a/js/binary/proto_test.js +++ b/js/binary/proto_test.js @@ -423,8 +423,9 @@ describe('protoBinaryTest', function() { it('testRoundTrip', function() { var msg = new proto.jspb.test.TestAllTypes(); fillAllFields(msg); - var encoded = msg.serializeBinary(); - var decoded = proto.jspb.test.TestAllTypes.deserializeBinary(encoded); + var encoded = proto.binary.jspb.test.Proto3.serializeBinary(msg); + var decoded = + proto.binary.jspb.test.TestAllTypes.deserializeBinary(encoded); checkAllFields(msg, decoded); }); @@ -440,7 +441,8 @@ describe('protoBinaryTest', function() { assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES)); // Test binary serialize round trip doesn't break it. - msg = proto.jspb.test.TestAllTypes.deserializeBinary(msg.serializeBinary()); + var serialized = proto.binary.jspb.test.Proto3.serializeBinary(msg); + msg = proto.binary.jspb.test.TestAllTypes.deserializeBinary(serialized); assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES)); assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES)); assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES)); @@ -621,8 +623,8 @@ describe('protoBinaryTest', function() { it('testExtensions', function() { var msg = new proto.jspb.test.TestExtendable(); fillExtensions(msg); - var encoded = msg.serializeBinary(); - var decoded = proto.jspb.test.TestExtendable.deserializeBinary(encoded); + var encoded = proto.binary.jspb.test.Proto3.serializeBinary(msg); + var decoded = proto.binary.jspb.test.TestExtendable.deserializeBinary(encoded); checkExtensions(decoded); }); }); diff --git a/js/gulpfile.js b/js/gulpfile.js index cca99131..324aad32 100644 --- a/js/gulpfile.js +++ b/js/gulpfile.js @@ -24,7 +24,7 @@ var wellKnownTypes = [ ]; gulp.task('genproto_closure', function (cb) { - exec(protoc + ' --js_out=library=testproto_libs,binary:. -I ../src -I . *.proto ../src/google/protobuf/descriptor.proto', + exec(protoc + ' --js_out=library=testproto_libs:. --jsbinary_out=library=testproto_binary_libs:. -I ../src -I . *.proto ../src/google/protobuf/descriptor.proto', function (err, stdout, stderr) { console.log(stdout); console.log(stderr); @@ -33,7 +33,7 @@ gulp.task('genproto_closure', function (cb) { }); gulp.task('genproto_commonjs', function (cb) { - exec('mkdir -p commonjs_out && ' + protoc + ' --js_out=import_style=commonjs,binary:commonjs_out -I ../src -I commonjs -I . *.proto commonjs/test*/*.proto ../src/google/protobuf/descriptor.proto', + exec('mkdir -p commonjs_out && ' + protoc + ' --js_out=import_style=commonjs:commonjs_out --jsbinary_out=import_style=commonjs:commonjs_out -I ../src -I commonjs -I . *.proto commonjs/test*/*.proto ../src/google/protobuf/descriptor.proto', function (err, stdout, stderr) { console.log(stdout); console.log(stderr); @@ -42,7 +42,7 @@ gulp.task('genproto_commonjs', function (cb) { }); gulp.task('genproto_commonjs_wellknowntypes', function (cb) { - exec('mkdir -p commonjs_out/node_modules/google-protobuf && ' + protoc + ' --js_out=import_style=commonjs,binary:commonjs_out/node_modules/google-protobuf -I ../src ../src/google/protobuf/descriptor.proto', + exec('mkdir -p commonjs_out/node_modules/google-protobuf && ' + protoc + ' --js_out=import_style=commonjs:commonjs_out/node_modules/google-protobuf --jsbinary_out=import_style=commonjs:commonjs_out/node_modules/google-protobuf -I ../src ../src/google/protobuf/descriptor.proto', function (err, stdout, stderr) { console.log(stdout); console.log(stderr); @@ -51,7 +51,7 @@ gulp.task('genproto_commonjs_wellknowntypes', function (cb) { }); gulp.task('genproto_wellknowntypes', function (cb) { - exec(protoc + ' --js_out=import_style=commonjs,binary:. -I ../src ' + wellKnownTypes.join(' '), + exec(protoc + ' --js_out=import_style=commonjs:. --jsbinary_out=import_style=commonjs:. -I ../src ' + wellKnownTypes.join(' '), function (err, stdout, stderr) { console.log(stdout); console.log(stderr); diff --git a/js/proto3_test.js b/js/proto3_test.js index fab0fd44..a87bd0e7 100644 --- a/js/proto3_test.js +++ b/js/proto3_test.js @@ -38,6 +38,9 @@ goog.require('proto.jspb.test.ForeignMessage'); goog.require('proto.jspb.test.Proto3Enum'); goog.require('proto.jspb.test.TestProto3'); +// CommonJS-LoadFromFile: proto3_test_binarypb proto.binary.jspb.test +goog.require('proto.binary.jspb.test.TestProto3'); + var BYTES = new Uint8Array([1, 2, 8, 9]); var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES); @@ -168,8 +171,8 @@ describe('proto3Test', function() { msg.setOneofString('asdf'); - var serialized = msg.serializeBinary(); - msg = proto.jspb.test.TestProto3.deserializeBinary(serialized); + var serialized = proto.binary.jspb.test.Proto3.serializeBinary(msg); + msg = proto.binary.jspb.test.TestProto3.deserializeBinary(serialized); assertEquals(msg.getOptionalInt32(), -42); assertEquals(msg.getOptionalInt64(), -0x7fffffff00000000); @@ -297,7 +300,7 @@ describe('proto3Test', function() { msg.setOneofUint32(null); - var serialized = msg.serializeBinary(); + var serialized = proto.binary.jspb.test.Proto3.serializeBinary(msg); assertEquals(0, serialized.length); }); @@ -313,7 +316,8 @@ describe('proto3Test', function() { assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES)); // Test binary serialize round trip doesn't break it. - msg = proto.jspb.test.TestProto3.deserializeBinary(msg.serializeBinary()); + var serialized = proto.binary.jspb.test.Proto3.serializeBinary(msg); + msg = proto.binary.jspb.test.TestProto3.deserializeBinary(serialized); assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES)); assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES)); assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES)); diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc index 58c77d00..cd016082 100755 --- a/src/google/protobuf/compiler/js/js_generator.cc +++ b/src/google/protobuf/compiler/js/js_generator.cc @@ -153,8 +153,12 @@ string StripProto(const string& filename) { // Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript // file foo/bar/baz.js. -string GetJSFilename(const string& filename) { - return StripProto(filename) + "_pb.js"; +string GetJSFilename(bool binary, const string& filename) { + if (binary) { + return StripProto(filename) + "_binarypb.js"; + } else { + return StripProto(filename) + "_pb.js"; + } } // Given a filename like foo/bar/baz.proto, returns the root directory @@ -197,33 +201,52 @@ string ModuleAlias(const string& filename) { // Returns the fully normalized JavaScript path for the given // file descriptor's package. -string GetPath(const GeneratorOptions& options, - const FileDescriptor* file) { +string GetFilePathMaybeBinary(bool binary, + const GeneratorOptions& options, + const FileDescriptor* file) { + const string binary_namespace = binary ? ".binary" : ""; if (!options.namespace_prefix.empty()) { - return options.namespace_prefix; + return options.namespace_prefix + binary_namespace; } else if (!file->package().empty()) { - return "proto." + file->package(); + return "proto" + binary_namespace + "." + file->package(); } else { - return "proto"; + return "proto" + binary_namespace; } } +string GetFilePath(const GeneratorOptions& options, + const FileDescriptor* file) { + return GetFilePathMaybeBinary(false, options, file); +} + +string GetFilePathBinary(const GeneratorOptions& options, + const FileDescriptor* file) { + return GetFilePathMaybeBinary(true, options, file); +} + // Forward declare, so that GetPrefix can call this method, // which in turn, calls GetPrefix. -string GetPath(const GeneratorOptions& options, +string GetMessagePath(const GeneratorOptions& options, + const Descriptor* descriptor); +string GetMessagePathBinary(const GeneratorOptions& options, const Descriptor* descriptor); // Returns the path prefix for a message or enumeration that // lives under the given file and containing type. -string GetPrefix(const GeneratorOptions& options, +string GetPrefix(bool binary, + const GeneratorOptions& options, const FileDescriptor* file_descriptor, const Descriptor* containing_type) { string prefix = ""; if (containing_type == NULL) { - prefix = GetPath(options, file_descriptor); + prefix = binary ? + GetFilePathBinary(options, file_descriptor) : + GetFilePath(options, file_descriptor); } else { - prefix = GetPath(options, containing_type); + prefix = binary ? + GetMessagePathBinary(options, containing_type) : + GetMessagePath(options, containing_type); } if (!prefix.empty()) { @@ -233,43 +256,31 @@ string GetPrefix(const GeneratorOptions& options, return prefix; } - // Returns the fully normalized JavaScript path for the given // message descriptor. -string GetPath(const GeneratorOptions& options, +string GetMessagePath(const GeneratorOptions& options, const Descriptor* descriptor) { - return GetPrefix( + return GetPrefix(false, options, descriptor->file(), descriptor->containing_type()) + descriptor->name(); } - -// Returns the fully normalized JavaScript path for the given -// field's containing message descriptor. -string GetPath(const GeneratorOptions& options, - const FieldDescriptor* descriptor) { - return GetPath(options, descriptor->containing_type()); +string GetMessagePathBinary(const GeneratorOptions& options, + const Descriptor* descriptor) { + return GetPrefix(true, + options, descriptor->file(), + descriptor->containing_type()) + descriptor->name(); } // Returns the fully normalized JavaScript path for the given // enumeration descriptor. -string GetPath(const GeneratorOptions& options, - const EnumDescriptor* enum_descriptor) { - return GetPrefix( +string GetEnumPath(const GeneratorOptions& options, + const EnumDescriptor* enum_descriptor) { + return GetPrefix(false, options, enum_descriptor->file(), enum_descriptor->containing_type()) + enum_descriptor->name(); } - -// Returns the fully normalized JavaScript path for the given -// enumeration value descriptor. -string GetPath(const GeneratorOptions& options, - const EnumValueDescriptor* value_descriptor) { - return GetPath( - options, - value_descriptor->type()) + "." + value_descriptor->name(); -} - string MaybeCrossFileRef(const GeneratorOptions& options, const FileDescriptor* from_file, const Descriptor* to_message) { @@ -280,7 +291,7 @@ string MaybeCrossFileRef(const GeneratorOptions& options, return ModuleAlias(to_message->file()->name()) + "." + to_message->name(); } else { // Within a single file we use a full name. - return GetPath(options, to_message); + return GetMessagePath(options, to_message); } } @@ -405,7 +416,8 @@ string ToFileName(const string& input) { // that top-level extensions should go in. string GetExtensionFileName(const GeneratorOptions& options, const FileDescriptor* file) { - return options.output_dir + "/" + ToFileName(GetPath(options, file)) + ".js"; + return options.output_dir + "/" + + ToFileName(GetFilePath(options, file)) + ".js"; } // When we're generating one output file per type name, this is the filename @@ -531,15 +543,6 @@ string JSGetterName(const GeneratorOptions& options, return name; } -string JSMapGetterName(const GeneratorOptions& options, - const FieldDescriptor* field) { - return JSIdent(options, field, - /* is_upper_camel = */ true, - /* is_map = */ true); -} - - - string JSOneofName(const OneofDescriptor* oneof) { return ToUpperCamel(ParseLowerUnderscore(oneof->name())); } @@ -848,11 +851,11 @@ string ProtoTypeName(const GeneratorOptions& options, case FieldDescriptor::TYPE_BYTES: return "bytes"; case FieldDescriptor::TYPE_GROUP: - return GetPath(options, field->message_type()); + return GetMessagePath(options, field->message_type()); case FieldDescriptor::TYPE_ENUM: - return GetPath(options, field->enum_type()); + return GetEnumPath(options, field->enum_type()); case FieldDescriptor::TYPE_MESSAGE: - return GetPath(options, field->message_type()); + return GetMessagePath(options, field->message_type()); default: return ""; } @@ -901,9 +904,9 @@ string JSTypeName(const GeneratorOptions& options, case FieldDescriptor::CPPTYPE_STRING: return JSStringTypeName(options, field, bytes_mode); case FieldDescriptor::CPPTYPE_ENUM: - return GetPath(options, field->enum_type()); + return GetEnumPath(options, field->enum_type()); case FieldDescriptor::CPPTYPE_MESSAGE: - return GetPath(options, field->message_type()); + return GetMessagePath(options, field->message_type()); default: return ""; } @@ -980,22 +983,14 @@ string JSBinaryReadWriteMethodName(const FieldDescriptor* field, string JSBinaryReaderMethodName(const GeneratorOptions& options, const FieldDescriptor* field) { - if (options.binary) { - return "jspb.BinaryReader.prototype.read" + - JSBinaryReadWriteMethodName(field, /* is_writer = */ false); - } else { - return "null"; - } + return "jspb.BinaryReader.prototype.read" + + JSBinaryReadWriteMethodName(field, /* is_writer = */ false); } string JSBinaryWriterMethodName(const GeneratorOptions& options, const FieldDescriptor* field) { - if (options.binary) { - return "jspb.BinaryWriter.prototype.write" + - JSBinaryReadWriteMethodName(field, /* is_writer = */ true); - } else { - return "null"; - } + return "jspb.BinaryWriter.prototype.write" + + JSBinaryReadWriteMethodName(field, /* is_writer = */ true); } string JSReturnClause(const FieldDescriptor* desc) { @@ -1021,7 +1016,7 @@ static const char* kRepeatedFieldArrayName = ".repeatedFields_"; string RepeatedFieldsArrayName(const GeneratorOptions& options, const Descriptor* desc) { return HasRepeatedFields(desc) ? - (GetPath(options, desc) + kRepeatedFieldArrayName) : "null"; + (GetMessagePath(options, desc) + kRepeatedFieldArrayName) : "null"; } bool HasOneofFields(const Descriptor* desc) { @@ -1038,7 +1033,7 @@ static const char* kOneofGroupArrayName = ".oneofGroups_"; string OneofFieldsArrayName(const GeneratorOptions& options, const Descriptor* desc) { return HasOneofFields(desc) ? - (GetPath(options, desc) + kOneofGroupArrayName) : "null"; + (GetMessagePath(options, desc) + kOneofGroupArrayName) : "null"; } string RepeatedFieldNumberList(const Descriptor* desc) { @@ -1479,7 +1474,7 @@ void Generator::FindProvidesForMessage( return; } - string name = GetPath(options, desc); + string name = GetMessagePath(options, desc); provided->insert(name); for (int i = 0; i < desc->enum_type_count(); i++) { @@ -1496,7 +1491,7 @@ void Generator::FindProvidesForEnum(const GeneratorOptions& options, io::Printer* printer, const EnumDescriptor* enumdesc, std::set* provided) const { - string name = GetPath(options, enumdesc); + string name = GetEnumPath(options, enumdesc); provided->insert(name); } @@ -1513,7 +1508,7 @@ void Generator::FindProvidesForFields( } string name = - GetPath(options, field->file()) + "." + + GetFilePath(options, field->file()) + "." + JSObjectFieldName(options, field); provided->insert(name); } @@ -1575,7 +1570,7 @@ void Generator::GenerateRequiresForLibrary( } if (extension->containing_type()->full_name() != "google.protobuf.bridge.MessageSet") { - required.insert(GetPath(options, extension->containing_type())); + required.insert(GetMessagePath(options, extension->containing_type())); } FindRequiresForField(options, extension, &required, &forwards); have_extensions = true; @@ -1614,12 +1609,12 @@ void Generator::GenerateRequiresImpl(const GeneratorOptions& options, bool require_jspb, bool require_extension) const { if (require_jspb) { - printer->Print( - "goog.require('jspb.Message');\n"); - if (options.binary) { + if (binary_) { printer->Print( "goog.require('jspb.BinaryReader');\n" "goog.require('jspb.BinaryWriter');\n"); + } else { + printer->Print("goog.require('jspb.Message');\n"); } } if (require_extension) { @@ -1693,13 +1688,13 @@ void Generator::FindRequiresForField(const GeneratorOptions& options, // dependencies, as per original codegen. !(field->is_extension() && field->extension_scope() == NULL)) { if (options.add_require_for_enums) { - required->insert(GetPath(options, field->enum_type())); + required->insert(GetEnumPath(options, field->enum_type())); } else { - forwards->insert(GetPath(options, field->enum_type())); + forwards->insert(GetEnumPath(options, field->enum_type())); } } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (!IgnoreMessage(options, field->message_type())) { - required->insert(GetPath(options, field->message_type())); + required->insert(GetMessagePath(options, field->message_type())); } } } @@ -1709,7 +1704,7 @@ void Generator::FindRequiresForExtension(const GeneratorOptions& options, std::set* required, std::set* forwards) const { if (field->containing_type()->full_name() != "google.protobuf.bridge.MessageSet") { - required->insert(GetPath(options, field->containing_type())); + required->insert(GetMessagePath(options, field->containing_type())); } FindRequiresForField(options, field, required, forwards); } @@ -1742,22 +1737,23 @@ void Generator::GenerateClass(const GeneratorOptions& options, if (!NamespaceOnly(desc)) { printer->Print("\n"); - GenerateClassConstructor(options, printer, desc); - GenerateClassFieldInfo(options, printer, desc); - - - GenerateClassToObject(options, printer, desc); - if (options.binary) { + if (binary_) { // These must come *before* the extension-field info generation in // GenerateClassRegistration so that references to the binary // serialization/deserialization functions may be placed in the extension // objects. GenerateClassDeserializeBinary(options, printer, desc); GenerateClassSerializeBinary(options, printer, desc); + } else { + GenerateClassConstructor(options, printer, desc); + GenerateClassFieldInfo(options, printer, desc); + + GenerateClassToObject(options, printer, desc); + GenerateClassClone(options, printer, desc); + GenerateClassRegistration(options, printer, desc); + GenerateClassFields(options, printer, desc); } - GenerateClassClone(options, printer, desc); - GenerateClassRegistration(options, printer, desc); - GenerateClassFields(options, printer, desc); + if (IsExtendable(desc) && desc->full_name() != "google.protobuf.bridge.MessageSet") { GenerateClassExtensionFieldInfo(options, printer, desc); } @@ -1797,7 +1793,7 @@ void Generator::GenerateClassConstructor(const GeneratorOptions& options, " * @constructor\n" " */\n" "$classname$ = function(opt_data) {\n", - "classname", GetPath(options, desc)); + "classname", GetMessagePath(options, desc)); string message_id = GetMessageId(desc); printer->Print( " jspb.Message.initialize(this, opt_data, $messageId$, $pivot$, " @@ -1814,7 +1810,7 @@ void Generator::GenerateClassConstructor(const GeneratorOptions& options, "if (goog.DEBUG && !COMPILED) {\n" " $classname$.displayName = '$classname$';\n" "}\n", - "classname", GetPath(options, desc)); + "classname", GetMessagePath(options, desc)); } void Generator::GenerateClassFieldInfo(const GeneratorOptions& options, @@ -1829,7 +1825,7 @@ void Generator::GenerateClassFieldInfo(const GeneratorOptions& options, " */\n" "$classname$$rptfieldarray$ = $rptfields$;\n" "\n", - "classname", GetPath(options, desc), + "classname", GetMessagePath(options, desc), "rptfieldarray", kRepeatedFieldArrayName, "rptfields", RepeatedFieldNumberList(desc)); } @@ -1850,7 +1846,7 @@ void Generator::GenerateClassFieldInfo(const GeneratorOptions& options, " */\n" "$classname$$oneofgrouparray$ = $oneofgroups$;\n" "\n", - "classname", GetPath(options, desc), + "classname", GetMessagePath(options, desc), "oneofgrouparray", kOneofGroupArrayName, "oneofgroups", OneofGroupList(desc)); @@ -1870,7 +1866,7 @@ void Generator::GenerateClassXid(const GeneratorOptions& options, "\n" "\n" "$class$.prototype.messageXid = xid('$class$');\n", - "class", GetPath(options, desc)); + "class", GetMessagePath(options, desc)); } void Generator::GenerateOneofCaseDefinition( @@ -1883,7 +1879,7 @@ void Generator::GenerateOneofCaseDefinition( " */\n" "$classname$.$oneof$Case = {\n" " $upcase$_NOT_SET: 0", - "classname", GetPath(options, oneof->containing_type()), + "classname", GetMessagePath(options, oneof->containing_type()), "oneof", JSOneofName(oneof), "upcase", ToEnumCase(oneof->name())); @@ -1911,7 +1907,7 @@ void Generator::GenerateOneofCaseDefinition( "computeOneofCase(this, $class$.oneofGroups_[$oneofindex$]));\n" "};\n" "\n", - "class", GetPath(options, oneof->containing_type()), + "class", GetMessagePath(options, oneof->containing_type()), "oneof", JSOneofName(oneof), "oneofindex", JSOneofIndex(oneof)); } @@ -1953,7 +1949,7 @@ void Generator::GenerateClassToObject(const GeneratorOptions& options, " */\n" "$classname$.toObject = function(includeInstance, msg) {\n" " var f, obj = {", - "classname", GetPath(options, desc)); + "classname", GetMessagePath(options, desc)); bool first = true; for (int i = 0; i < desc->field_count(); i++) { @@ -1985,7 +1981,7 @@ void Generator::GenerateClassToObject(const GeneratorOptions& options, " $extObject$, $class$.prototype.getExtension,\n" " includeInstance);\n", "extObject", JSExtensionsObjectName(options, desc->file(), desc), - "class", GetPath(options, desc)); + "class", GetMessagePath(options, desc)); } printer->Print( @@ -1997,7 +1993,7 @@ void Generator::GenerateClassToObject(const GeneratorOptions& options, "}\n" "\n" "\n", - "classname", GetPath(options, desc)); + "classname", GetMessagePath(options, desc)); } void Generator::GenerateClassFieldToObject(const GeneratorOptions& options, @@ -2074,7 +2070,7 @@ void Generator::GenerateClassFromObject(const GeneratorOptions& options, " */\n" "$classname$.fromObject = function(obj) {\n" " var f, msg = new $classname$();\n", - "classname", GetPath(options, desc)); + "classname", GetMessagePath(options, desc)); for (int i = 0; i < desc->field_count(); i++) { const FieldDescriptor* field = desc->field(i); @@ -2145,7 +2141,7 @@ void Generator::GenerateClassClone(const GeneratorOptions& options, "$name$.prototype.cloneMessage = function() {\n" " return /** @type {!$name$} */ (jspb.Message.cloneMessage(this));\n" "};\n\n\n", - "name", GetPath(options, desc)); + "name", GetMessagePath(options, desc)); } void Generator::GenerateClassRegistration(const GeneratorOptions& options, @@ -2197,7 +2193,7 @@ void GenerateBytesWrapper(const GeneratorOptions& options, "fielddef", FieldDefinition(options, field), "comment", FieldComments(field, bytes_mode), "type", type, - "class", GetPath(options, field->containing_type()), + "class", GetMessagePath(options, field->containing_type()), "name", JSGetterName(options, field, bytes_mode), "list", field->is_repeated() ? "List" : "", "suffix", JSByteGetterSuffix(bytes_mode), @@ -2238,7 +2234,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, printer->Print( "$class$.prototype.get$name$ = function(opt_noLazyCreate) {\n" " return /** @type {!jspb.Map<$keytype$,$valuetype$>} */ (\n", - "class", GetPath(options, field->containing_type()), + "class", GetMessagePath(options, field->containing_type()), "name", JSGetterName(options, field), "keytype", key_type, "valuetype", value_type); @@ -2249,10 +2245,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { printer->Print(",\n" " $messageType$", - "messageType", GetPath(options, value_field->message_type())); - } else if (options.binary) { - printer->Print(",\n" - " null"); + "messageType", GetMessagePath(options, value_field->message_type())); } printer->Print( @@ -2286,7 +2279,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, "};\n" "\n" "\n", - "class", GetPath(options, field->containing_type()), + "class", GetMessagePath(options, field->containing_type()), "name", JSGetterName(options, field), "type", JSFieldTypeAnnotation(options, field, /* force_optional = */ false, @@ -2307,7 +2300,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, /* force_present = */ false, /* singular_if_not_packed = */ false), "returndoc", JSReturnDoc(options, field), - "class", GetPath(options, field->containing_type()), + "class", GetMessagePath(options, field->containing_type()), "name", JSGetterName(options, field), "oneoftag", (field->containing_oneof() ? "Oneof" : ""), "repeatedtag", (field->is_repeated() ? "Repeated" : "")); @@ -2328,7 +2321,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, "};\n" "\n" "\n", - "class", GetPath(options, field->containing_type()), + "class", GetMessagePath(options, field->containing_type()), "name", JSGetterName(options, field), "clearedvalue", (field->is_repeated() ? "[]" : "undefined"), "returnvalue", JSReturnClause(field)); @@ -2343,7 +2336,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, // at this point we "lie" to non-binary users and tell the the return // type is always base64 string, pending a LSC to migrate to typed getters. BytesMode bytes_mode = - field->type() == FieldDescriptor::TYPE_BYTES && !options.binary ? + field->type() == FieldDescriptor::TYPE_BYTES && options.legacy_bytes_fields ? BYTES_B64 : BYTES_DEFAULT; string typed_annotation = JSFieldTypeAnnotation(options, field, @@ -2370,7 +2363,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, printer->Print( "$class$.prototype.get$name$ = function() {\n", - "class", GetPath(options, field->containing_type()), + "class", GetMessagePath(options, field->containing_type()), "name", JSGetterName(options, field)); if (untyped) { @@ -2450,7 +2443,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, printer->Print( "$class$.prototype.set$name$ = function(value) {\n" " jspb.Message.set$oneoftag$Field(this, $index$", - "class", GetPath(options, field->containing_type()), + "class", GetMessagePath(options, field->containing_type()), "name", JSGetterName(options, field), "oneoftag", (field->containing_oneof() ? "Oneof" : ""), "index", JSFieldIndex(field)); @@ -2480,7 +2473,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, printer->Print( "$class$.prototype.clear$name$ = function() {\n" " jspb.Message.set$oneoftag$Field(this, $index$$oneofgroup$, ", - "class", GetPath(options, field->containing_type()), + "class", GetMessagePath(options, field->containing_type()), "name", JSGetterName(options, field), "oneoftag", (field->containing_oneof() ? "Oneof" : ""), "oneofgroup", (field->containing_oneof() ? @@ -2507,7 +2500,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, "};\n" "\n" "\n", - "class", GetPath(options, field->containing_type()), + "class", GetMessagePath(options, field->containing_type()), "name", JSGetterName(options, field), "index", JSFieldIndex(field)); } @@ -2536,9 +2529,9 @@ void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options, " */\n" "$class$.extensions = {};\n" "\n", - "class", GetPath(options, desc)); + "class", GetMessagePath(options, desc)); - if (options.binary) { + if (binary_) { printer->Print( "\n" "/**\n" @@ -2558,7 +2551,7 @@ void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options, " */\n" "$class$.extensionsBinary = {};\n" "\n", - "class", GetPath(options, desc)); + "class", GetMessagePath(options, desc)); } } } @@ -2597,7 +2590,7 @@ void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options, " }\n" " var field = reader.getFieldNumber();\n" " switch (field) {\n", - "class", GetPath(options, desc)); + "class", GetMessagePathBinary(options, desc)); for (int i = 0; i < desc->field_count(); i++) { GenerateClassDeserializeBinaryField(options, printer, desc->field(i)); @@ -2612,7 +2605,7 @@ void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options, " $class$.prototype.setExtension);\n" " break;\n", "extobj", JSExtensionsObjectName(options, desc->file(), desc), - "class", GetPath(options, desc)); + "class", GetMessagePathBinary(options, desc)); } else { printer->Print( " reader.skipField();\n" @@ -2651,7 +2644,8 @@ void Generator::GenerateClassDeserializeBinaryField( if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { printer->Print(", $messageType$.deserializeBinaryFromReader", - "messageType", GetPath(options, value_field->message_type())); + "messageType", + GetMessagePathBinary(options, value_field->message_type())); } printer->Print(");\n"); @@ -2733,7 +2727,7 @@ void Generator::GenerateClassSerializeBinary(const GeneratorOptions& options, " */\n" "$class$.prototype.serializeBinaryToWriter = function (writer) {\n" " var f = undefined;\n", - "class", GetPath(options, desc)); + "class", GetMessagePathBinary(options, desc)); for (int i = 0; i < desc->field_count(); i++) { GenerateClassSerializeBinaryField(options, printer, desc->field(i)); @@ -2744,7 +2738,7 @@ void Generator::GenerateClassSerializeBinary(const GeneratorOptions& options, " jspb.Message.serializeBinaryExtensions(this, writer,\n" " $extobj$Binary, $class$.prototype.getExtension);\n", "extobj", JSExtensionsObjectName(options, desc->file(), desc), - "class", GetPath(options, desc)); + "class", GetMessagePathBinary(options, desc)); } printer->Print( @@ -2832,7 +2826,7 @@ void Generator::GenerateClassSerializeBinaryField( if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { printer->Print(", $messageType$.serializeBinaryToWriter", - "messageType", GetPath(options, value_field->message_type())); + "messageType", GetMessagePathBinary(options, value_field->message_type())); } printer->Print(");\n"); @@ -2871,7 +2865,7 @@ void Generator::GenerateEnum(const GeneratorOptions& options, " * @enum {number}\n" " */\n" "$name$ = {\n", - "name", GetPath(options, enumdesc)); + "name", GetEnumPath(options, enumdesc)); for (int i = 0; i < enumdesc->value_count(); i++) { const EnumValueDescriptor* value = enumdesc->value(i); @@ -2890,44 +2884,14 @@ void Generator::GenerateEnum(const GeneratorOptions& options, void Generator::GenerateExtension(const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* field) const { + string message_path = binary_ ? + GetMessagePathBinary(options, field->extension_scope()) : + GetMessagePath(options, field->extension_scope()); string extension_scope = (field->extension_scope() ? - GetPath(options, field->extension_scope()) : - GetPath(options, field->file())); + message_path : GetFilePath(options, field->file())); - printer->Print( - "\n" - "/**\n" - " * A tuple of {field number, class constructor} for the extension\n" - " * field named `$name$`.\n" - " * @type {!jspb.ExtensionFieldInfo.<$extensionType$>}\n" - " */\n" - "$class$.$name$ = new jspb.ExtensionFieldInfo(\n", - "name", JSObjectFieldName(options, field), - "class", extension_scope, - "extensionType", JSFieldTypeAnnotation( - options, field, - /* force_optional = */ false, - /* force_present = */ true, - /* singular_if_not_packed = */ false)); - printer->Print( - " $index$,\n" - " {$name$: 0},\n" - " $ctor$,\n" - " /** @type {?function((boolean|undefined),!jspb.Message=): " - "!Object} */ (\n" - " $toObject$),\n" - " $repeated$);\n", - "index", SimpleItoa(field->number()), - "name", JSObjectFieldName(options, field), - "ctor", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ? - SubmessageTypeRef(options, field) : string("null")), - "toObject", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ? - (SubmessageTypeRef(options, field) + ".toObject") : - string("null")), - "repeated", (field->is_repeated() ? "1" : "0")); - - if (options.binary) { + if (binary_) { printer->Print( "\n" "$extendName$Binary[$index$] = new jspb.ExtensionFieldBinaryInfo(\n" @@ -2955,18 +2919,50 @@ void Generator::GenerateExtension(const GeneratorOptions& options, printer->Print( " $isPacked$);\n", "isPacked", (field->is_packed() ? "true" : "false")); - } + } else { + printer->Print( + "\n" + "/**\n" + " * A tuple of {field number, class constructor} for the extension\n" + " * field named `$name$`.\n" + " * @type {!jspb.ExtensionFieldInfo.<$extensionType$>}\n" + " */\n" + "$class$.$name$ = new jspb.ExtensionFieldInfo(\n", + "name", JSObjectFieldName(options, field), + "class", extension_scope, + "extensionType", JSFieldTypeAnnotation( + options, field, + /* force_optional = */ false, + /* force_present = */ true, + /* singular_if_not_packed = */ false)); + printer->Print( + " $index$,\n" + " {$name$: 0},\n" + " $ctor$,\n" + " /** @type {?function((boolean|undefined),!jspb.Message=): " + "!Object} */ (\n" + " $toObject$),\n" + " $repeated$);\n", + "index", SimpleItoa(field->number()), + "name", JSObjectFieldName(options, field), + "ctor", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ? + SubmessageTypeRef(options, field) : string("null")), + "toObject", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ? + (SubmessageTypeRef(options, field) + ".toObject") : + string("null")), + "repeated", (field->is_repeated() ? "1" : "0")); - printer->Print( - "// This registers the extension field with the extended class, so that\n" - "// toObject() will function correctly.\n" - "$extendName$[$index$] = $class$.$name$;\n" - "\n", - "extendName", JSExtensionsObjectName(options, field->file(), - field->containing_type()), - "index", SimpleItoa(field->number()), - "class", extension_scope, - "name", JSObjectFieldName(options, field)); + printer->Print( + "// This registers the extension field with the extended class, so that\n" + "// toObject() will function correctly.\n" + "$extendName$[$index$] = $class$.$name$;\n" + "\n", + "extendName", JSExtensionsObjectName(options, field->file(), + field->containing_type()), + "index", SimpleItoa(field->number()), + "class", extension_scope, + "name", JSObjectFieldName(options, field)); + } } bool GeneratorOptions::ParseFromOptions( @@ -2984,7 +2980,8 @@ bool GeneratorOptions::ParseFromOptions( *error = "Unexpected option value for binary"; return false; } - binary = true; + GOOGLE_LOG(WARNING) << "js_generator.cc: WARNING, binary=1 is deprecated," + << " use jsbinary_out=dir instead.\n"; } else if (options[i].first == "testonly") { if (options[i].second != "") { *error = "Unexpected option value for testonly"; @@ -3089,9 +3086,10 @@ void Generator::GenerateFile(const GeneratorOptions& options, for (int i = 0; i < file->dependency_count(); i++) { const string& name = file->dependency(i)->name(); printer->Print( - "var $alias$ = require('$file$');\n", + "var $alias$ = require('$path$$file$');\n", "alias", ModuleAlias(name), - "file", GetRootPath(file->name(), name) + GetJSFilename(name)); + "path", GetRootPath(file->name(), name), + "file", GetJSFilename(binary_, name)); } } @@ -3107,9 +3105,7 @@ void Generator::GenerateFile(const GeneratorOptions& options, // Cover the case where this file declares extensions but no messages. // This will ensure that the file-level object will be declared to hold // the extensions. - for (int i = 0; i < file->extension_count(); i++) { - provided.insert(file->extension(i)->full_name()); - } + provided.insert(GetFilePath(options, file)); FindProvidesForFile(options, printer, file, &provided); for (std::set::iterator it = provided.begin(); @@ -3128,7 +3124,7 @@ void Generator::GenerateFile(const GeneratorOptions& options, if (options.import_style == GeneratorOptions::IMPORT_COMMONJS) { printer->Print("goog.object.extend(exports, $package$);\n", - "package", GetPath(options, file)); + "package", GetFilePath(options, file)); } } @@ -3285,8 +3281,10 @@ bool Generator::GenerateAll(const vector& files, for (int i = 0; i < files.size(); i++) { const google::protobuf::FileDescriptor* file = files[i]; - string filename = options.output_dir + "/" + GetJSFilename(file->name()); - google::protobuf::scoped_ptr output(context->Open(filename)); + string filename = options.output_dir + "/" + + GetJSFilename(binary_, file->name()); + google::protobuf::scoped_ptr output( + context->Open(filename)); GOOGLE_CHECK(output.get()); io::Printer printer(output.get(), '$'); diff --git a/src/google/protobuf/compiler/js/js_generator.h b/src/google/protobuf/compiler/js/js_generator.h index 6fd7ca50..d448d8ec 100755 --- a/src/google/protobuf/compiler/js/js_generator.h +++ b/src/google/protobuf/compiler/js/js_generator.h @@ -65,8 +65,8 @@ struct GeneratorOptions { string library; // Error if there are two types that would generate the same output file? bool error_on_name_conflict; - // Enable binary-format support? - bool binary; + // Whether to use legacy behavior for bytes fields. + bool legacy_bytes_fields; // What style of imports should be used. enum ImportStyle { IMPORT_CLOSURE, // goog.require() @@ -82,7 +82,7 @@ struct GeneratorOptions { namespace_prefix(""), library(""), error_on_name_conflict(false), - binary(false), + legacy_bytes_fields(false), import_style(IMPORT_CLOSURE) {} bool ParseFromOptions( @@ -92,7 +92,7 @@ struct GeneratorOptions { class LIBPROTOC_EXPORT Generator : public CodeGenerator { public: - Generator() {} + Generator(bool binary) : binary_(binary) {} virtual ~Generator() {} virtual bool Generate(const FileDescriptor* file, @@ -111,6 +111,8 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { string* error) const; private: + bool binary_; + void GenerateHeader(const GeneratorOptions& options, io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc index 2f3c5b8f..ef37909b 100644 --- a/src/google/protobuf/compiler/main.cc +++ b/src/google/protobuf/compiler/main.cc @@ -90,9 +90,12 @@ int main(int argc, char* argv[]) { "Generate Objective C header and source."); // JavaScript - google::protobuf::compiler::js::Generator js_generator; + google::protobuf::compiler::js::Generator js_generator(false); cli.RegisterGenerator("--js_out", &js_generator, "Generate JavaScript source."); + google::protobuf::compiler::js::Generator js_binary_generator(true); + cli.RegisterGenerator("--jsbinary_out", &js_binary_generator, + "Generate JavaScript binary parse/serialize source."); return cli.Run(argc, argv); } -- cgit v1.2.3