aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/compiler/js
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/compiler/js')
-rwxr-xr-xsrc/google/protobuf/compiler/js/js_generator.cc77
-rw-r--r--src/google/protobuf/compiler/js/well_known_types/any.js2
2 files changed, 50 insertions, 29 deletions
diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc
index 7c63e58f..ba078703 100755
--- a/src/google/protobuf/compiler/js/js_generator.cc
+++ b/src/google/protobuf/compiler/js/js_generator.cc
@@ -143,12 +143,16 @@ bool IsReserved(const string& ident) {
return false;
}
+bool StrEndsWith(StringPiece sp, StringPiece x) {
+ return sp.size() >= x.size() && sp.substr(sp.size() - x.size()) == x;
+}
+
// Returns a copy of |filename| with any trailing ".protodevel" or ".proto
// suffix stripped.
// TODO(haberman): Unify with copy in compiler/cpp/internal/helpers.cc.
string StripProto(const string& filename) {
- const char* suffix = HasSuffixString(filename, ".protodevel")
- ? ".protodevel" : ".proto";
+ const char* suffix =
+ StrEndsWith(filename, ".protodevel") ? ".protodevel" : ".proto";
return StripSuffixString(filename, suffix);
}
@@ -756,8 +760,22 @@ string DoubleToString(double value) {
return PostProcessFloat(result);
}
+// Return true if this is an integral field that should be represented as string
+// in JS.
+bool IsIntegralFieldWithStringJSType(const FieldDescriptor* field) {
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT64:
+ case FieldDescriptor::CPPTYPE_UINT64:
+ // The default value of JSType is JS_NORMAL, which behaves the same as
+ // JS_NUMBER.
+ return field->options().jstype() == google::protobuf::FieldOptions::JS_STRING;
+ default:
+ return false;
+ }
+}
+
string MaybeNumberString(const FieldDescriptor* field, const string& orig) {
- return orig;
+ return IsIntegralFieldWithStringJSType(field) ? ("\"" + orig + "\"") : orig;
}
string JSFieldDefault(const FieldDescriptor* field) {
@@ -856,7 +874,7 @@ string ProtoTypeName(const GeneratorOptions& options,
}
string JSIntegerTypeName(const FieldDescriptor* field) {
- return "number";
+ return IsIntegralFieldWithStringJSType(field) ? "string" : "number";
}
string JSStringTypeName(const GeneratorOptions& options,
@@ -1033,8 +1051,7 @@ string JSBinaryReaderMethodType(const FieldDescriptor* field) {
if (name[0] >= 'a' && name[0] <= 'z') {
name[0] = (name[0] - 'a') + 'A';
}
-
- return name;
+ return IsIntegralFieldWithStringJSType(field) ? (name + "String") : name;
}
string JSBinaryReadWriteMethodName(const FieldDescriptor* field,
@@ -1244,13 +1261,6 @@ string FieldComments(const FieldDescriptor* field, BytesMode bytes_mode) {
" * You should avoid comparisons like {@code val === true/false} in "
"those cases.\n";
}
- if (field->is_repeated()) {
- comments +=
- " * If you change this array by adding, removing or replacing "
- "elements, or if you\n"
- " * replace the array itself, then you must call the setter to "
- "update it.\n";
- }
if (field->type() == FieldDescriptor::TYPE_BYTES && bytes_mode == BYTES_U8) {
comments +=
" * Note that Uint8Array is not supported on all browsers.\n"
@@ -1323,7 +1333,7 @@ bool IsExtendable(const Descriptor* desc) {
// Returns the max index in the underlying data storage array beyond which the
// extension object is used.
string GetPivot(const Descriptor* desc) {
- static const int kDefaultPivot = (1 << 29); // max field number (29 bits)
+ static const int kDefaultPivot = 500;
// Find the max field number
int max_field_number = 0;
@@ -1335,7 +1345,7 @@ string GetPivot(const Descriptor* desc) {
}
int pivot = -1;
- if (IsExtendable(desc)) {
+ if (IsExtendable(desc) || (max_field_number >= kDefaultPivot)) {
pivot = ((max_field_number + 1) < kDefaultPivot) ?
(max_field_number + 1) : kDefaultPivot;
}
@@ -1507,6 +1517,10 @@ void Generator::GenerateHeader(const GeneratorOptions& options,
printer->Print("/**\n"
" * @fileoverview\n"
" * @enhanceable\n"
+ " * @suppress {messageConventions} JS Compiler reports an "
+ "error if a variable or\n"
+ " * field starts with 'MSG_' and isn't a translatable "
+ "message.\n"
" * @public\n"
" */\n"
"// GENERATED CODE -- DO NOT EDIT!\n"
@@ -1698,18 +1712,16 @@ void Generator::GenerateRequiresImpl(const GeneratorOptions& options,
bool require_jspb, bool require_extension,
bool require_map) const {
if (require_jspb) {
- printer->Print(
- "goog.require('jspb.Message');\n"
- "goog.require('jspb.BinaryReader');\n"
- "goog.require('jspb.BinaryWriter');\n");
+ required->insert("jspb.Message");
+ required->insert("jspb.BinaryReader");
+ required->insert("jspb.BinaryWriter");
}
if (require_extension) {
- printer->Print("goog.require('jspb.ExtensionFieldBinaryInfo');\n");
- printer->Print(
- "goog.require('jspb.ExtensionFieldInfo');\n");
+ required->insert("jspb.ExtensionFieldBinaryInfo");
+ required->insert("jspb.ExtensionFieldInfo");
}
if (require_map) {
- printer->Print("goog.require('jspb.Map');\n");
+ required->insert("jspb.Map");
}
std::set<string>::iterator it;
@@ -2037,6 +2049,7 @@ void Generator::GenerateClassToObject(const GeneratorOptions& options,
" * http://goto/soy-param-migration\n"
" * @param {!$classname$} msg The msg instance to transform.\n"
" * @return {!Object}\n"
+ " * @suppress {unusedLocalVariables} f is only used for nested messages\n"
" */\n"
"$classname$.toObject = function(includeInstance, msg) {\n"
" var f, obj = {",
@@ -2125,7 +2138,8 @@ void Generator::GenerateFieldValueExpression(io::Printer* printer,
"obj", obj_reference);
}
} else {
- printer->Print("jspb.Message.getField($obj$, $index$)",
+ printer->Print("jspb.Message.get$cardinality$Field($obj$, $index$)",
+ "cardinality", field->is_repeated() ? "Repeated" : "",
"index", JSFieldIndex(field),
"obj", obj_reference);
}
@@ -2333,7 +2347,6 @@ void GenerateBytesWrapper(const GeneratorOptions& options,
"defname", JSGetterName(options, field, BYTES_DEFAULT));
}
-
void Generator::GenerateClassField(const GeneratorOptions& options,
io::Printer* printer,
const FieldDescriptor* field) const {
@@ -2463,7 +2476,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
// Simple (primitive) field, either singular or repeated.
// TODO(b/26173701): Always use BYTES_DEFAULT for the getter return type;
- // at this point we "lie" to non-binary users and tell the the return
+ // at this point we "lie" to non-binary users and tell 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 ?
@@ -2910,6 +2923,7 @@ void Generator::GenerateClassSerializeBinary(const GeneratorOptions& options,
" * format), writing to the given BinaryWriter.\n"
" * @param {!$class$} message\n"
" * @param {!jspb.BinaryWriter} writer\n"
+ " * @suppress {unusedLocalVariables} f is only used for nested messages\n"
" */\n"
"$class$.serializeBinaryToWriter = function(message, "
"writer) {\n"
@@ -2982,7 +2996,13 @@ void Generator::GenerateClassSerializeBinaryField(
case FieldDescriptor::CPPTYPE_INT64:
case FieldDescriptor::CPPTYPE_UINT32:
case FieldDescriptor::CPPTYPE_UINT64: {
- {
+ if (IsIntegralFieldWithStringJSType(field)) {
+ // We can use `parseInt` here even though it will not be precise for
+ // 64-bit quantities because we are only testing for zero/nonzero,
+ // and JS numbers (64-bit floating point values, i.e., doubles) are
+ // integer-precise in the range that includes zero.
+ printer->Print(" if (parseInt(f, 10) !== 0) {\n");
+ } else {
printer->Print(" if (f !== 0) {\n");
}
break;
@@ -3306,7 +3326,8 @@ void Generator::GenerateFile(const GeneratorOptions& options,
printer->Print(
"var $alias$ = require('$file$');\n",
"alias", ModuleAlias(name),
- "file", GetRootPath(file->name(), name) + GetJSFilename(options, name));
+ "file",
+ GetRootPath(file->name(), name) + GetJSFilename(options, name));
}
}
diff --git a/src/google/protobuf/compiler/js/well_known_types/any.js b/src/google/protobuf/compiler/js/well_known_types/any.js
index 22f18919..d7ca6e3a 100644
--- a/src/google/protobuf/compiler/js/well_known_types/any.js
+++ b/src/google/protobuf/compiler/js/well_known_types/any.js
@@ -69,7 +69,7 @@ proto.google.protobuf.Any.prototype.pack = function(serialized, name,
* the binary data properly.
* @param {string} name The expected type name of this message object.
* @return {?T} If the name matched the expected name, returns the deserialized
- * object, otherwise returns undefined.
+ * object, otherwise returns null.
*/
proto.google.protobuf.Any.prototype.unpack = function(deserialize, name) {
if (this.getTypeName() == name) {