Changes to make flatbuffers javascript compatible with the closure compiler.

Change-Id: Iab8d66a8f34910029deb8a5ff5ec7ba50c5b3421
This commit is contained in:
Wouter van Oortmerssen
2017-02-08 17:08:47 -08:00
parent 60b11435e6
commit d7ba17dfe5
5 changed files with 76 additions and 4 deletions

View File

@@ -93,6 +93,12 @@ Additional options:
output (by default the case for C++ and JS), all code will end up in
this one file.
- `--no-js-exports` : Removes Node.js style export lines (useful for JS)
- `--goog-js-export` : Uses goog.exportsSymbol and goog.exportsProperty
instead of Node.js style exporting. Needed for compatibility with the
Google closure compiler (useful for JS).
- `--raw-binary` : Allow binaries without a file_indentifier to be read.
This may crash flatc given a mismatched schema.

View File

@@ -337,6 +337,7 @@ struct ServiceDef : public Definition {
struct IDLOptions {
bool strict_json;
bool skip_js_exports;
bool use_goog_js_export_format;
bool output_default_scalars_in_json;
int indent_step;
bool output_enum_identifiers;
@@ -378,6 +379,7 @@ struct IDLOptions {
IDLOptions()
: strict_json(false),
skip_js_exports(false),
use_goog_js_export_format(false),
output_default_scalars_in_json(false),
indent_step(2),
output_enum_identifiers(true), prefixed_enums(true), scoped_enums(false),

View File

@@ -2,6 +2,15 @@
/// @addtogroup flatbuffers_javascript_api
/// @{
/// @cond FLATBUFFERS_INTERNAL
/**
* @fileoverview
*
* Need to suppress 'global this' error so the Node.js export line doesn't cause
* closure compile to error out.
* @suppress {globalThis}
*/
/**
* @const
* @namespace
@@ -530,6 +539,10 @@ flatbuffers.Builder.prototype.offset = function() {
* @param {flatbuffers.ByteBuffer} bb The current buffer with the existing data
* @returns {flatbuffers.ByteBuffer} A new byte buffer with the old data copied
* to it. The data is located at the end of the buffer.
*
* uint8Array.set() formally takes {Array<number>|ArrayBufferView}, so to pass
* it a uint8Array we need to suppress the type check:
* @suppress {checkTypes}
*/
flatbuffers.Builder.growByteBuffer = function(bb) {
var old_buf_size = bb.capacity();

View File

@@ -86,6 +86,8 @@ std::string FlatCompiler::GetUsageString(const char* program_name) const {
" --escape-proto-ids Disable appending '_' in namespaces names.\n"
" --gen-object-api Generate an additional object-based API.\n"
" --cpp-ptr-type T Set object API pointer type (default std::unique_ptr)\n"
" --no-js-exports Removes Node.js style export lines in JS.\n"
" --goog-js-export Uses goog.exports* for closure compiler exporting in JS.\n"
" --raw-binary Allow binaries without file_indentifier to be read.\n"
" This may crash flatc given a mismatched schema.\n"
" --proto Input is a .proto, translate to .fbs.\n"
@@ -146,6 +148,8 @@ int FlatCompiler::Compile(int argc, const char** argv) {
opts.allow_non_utf8 = true;
} else if(arg == "--no-js-exports") {
opts.skip_js_exports = true;
} else if(arg == "--goog-js-export") {
opts.use_goog_js_export_format = true;
} else if(arg == "--defaults-json") {
opts.output_default_scalars_in_json = true;
} else if (arg == "--unknown-json") {

View File

@@ -113,7 +113,11 @@ class JsGenerator : public BaseGenerator {
code += "/**\n * @const\n * @namespace\n */\n";
if (it->find('.') == std::string::npos) {
code += "var ";
exports += "this." + *it + " = " + *it + ";\n";
if(parser_.opts.use_goog_js_export_format) {
exports += "goog.exportSymbol('" + *it + "', " + *it + ");\n";
} else {
exports += "this." + *it + " = " + *it + ";\n";
}
}
code += *it + " = " + *it + " || {};\n\n";
}
@@ -172,7 +176,12 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr,
GenDocComment(enum_def.doc_comment, code_ptr, "@enum");
if (enum_def.defined_namespace->components.empty()) {
code += "var ";
exports += "this." + enum_def.name + " = " + enum_def.name + ";\n";
if(parser_.opts.use_goog_js_export_format) {
exports += "goog.exportSymbol('" + enum_def.name + "', " + enum_def.name +
");\n";
} else {
exports += "this." + enum_def.name + " = " + enum_def.name + ";\n";
}
}
code += WrapInNameSpace(enum_def) + " = {\n";
for (auto it = enum_def.vals.vec.begin();
@@ -236,6 +245,9 @@ std::string GenDefaultValue(const Value &value, const std::string &context) {
if (auto val = value.type.enum_def->ReverseLookup(
atoi(value.constant.c_str()), false)) {
return WrapInNameSpace(*value.type.enum_def) + "." + val->name;
} else {
return "/** @type {" + WrapInNameSpace(*value.type.enum_def) + "} */ ("
+ value.constant + ")";
}
}
@@ -371,7 +383,12 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
std::string object_name = WrapInNameSpace(struct_def);
GenDocComment(struct_def.doc_comment, code_ptr, "@constructor");
if (isStatement) {
exports += "this." + struct_def.name + " = " + struct_def.name + ";\n";
if(parser_.opts.use_goog_js_export_format) {
exports += "goog.exportSymbol('" + struct_def.name + "', " +
struct_def.name + ");\n";
} else {
exports += "this." + struct_def.name + " = " + struct_def.name + ";\n";
}
code += "function " + object_name;
} else {
code += object_name + " = function";
@@ -526,7 +543,13 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
field.value.type.element == BASE_TYPE_ULONG) {
code += "this.bb.createLong(0, 0)";
} else if (IsScalar(field.value.type.element)) {
code += "0";
if (field.value.type.enum_def) {
code += "/** @type {" +
WrapInNameSpace(*field.value.type.enum_def) + "} */ (" +
field.value.constant + ")";
} else {
code += "0";
}
} else {
code += "null";
}
@@ -550,6 +573,12 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
}
code += "};\n\n";
if(parser_.opts.use_goog_js_export_format) {
exports += "goog.exportProperty(" + object_name + ".prototype, '" +
MakeCamel(field.name, false) + "', " + object_name + ".prototype." +
MakeCamel(field.name, false) + ");\n";
}
// Adds the mutable scalar value to the output
if (IsScalar(field.value.type.base_type) && parser.opts.mutable_buffer) {
std::string annotations = "@param {" + GenTypeName(field.value.type, true) + "} value\n";
@@ -564,6 +593,12 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
code += " this.bb.write" + MakeCamel(GenType(field.value.type)) + "(this.bb_pos + offset, value);\n";
code += " return true;\n";
code += "};\n\n";
if(parser_.opts.use_goog_js_export_format) {
exports += "goog.exportProperty(" + object_name +
".prototype, 'mutate_" + field.name + "', " + object_name +
".prototype.mutate_" + field.name + ");\n";
}
}
// Emit vector helpers
@@ -574,6 +609,12 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
code += "Length = function() {\n" + offset_prefix;
code += "this.bb.__vector_len(this.bb_pos + offset) : 0;\n};\n\n";
if(parser_.opts.use_goog_js_export_format) {
exports += "goog.exportProperty(" + object_name + ".prototype, '" +
MakeCamel(field.name, false) + "Length', " + object_name +
".prototype." + MakeCamel(field.name, false) + "Length);\n";
}
// For scalar types, emit a typed array helper
auto vectorType = field.value.type.VectorType();
if (IsScalar(vectorType.base_type) && !IsLong(vectorType.base_type)) {
@@ -583,6 +624,12 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
code += "new " + GenType(vectorType) + "Array(this.bb.bytes().buffer, "
"this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), "
"this.bb.__vector_len(this.bb_pos + offset)) : null;\n};\n\n";
if(parser_.opts.use_goog_js_export_format) {
exports += "goog.exportProperty(" + object_name + ".prototype, '" +
MakeCamel(field.name, false) + "Array', " + object_name +
".prototype." + MakeCamel(field.name, false) + "Array);\n";
}
}
}
}