Add support for JavaScript code generation

This adds a JavaScript language target. The generated JavaScript uses Google
Closure Compiler type annotations and can be compiled using the advanced
compilation mode, which performs type checking and optimizations such as
inlining and dead code elimination. The generated JavaScript also exports all
generated symbols for use with Node.js and RequireJS. This export behavior
can be turned off with the --no-js-exports flag for use with Google Closure
Compiler.
This commit is contained in:
Evan Wallace 2015-08-17 00:56:54 -07:00
parent 94680f5483
commit 224e33ed09
10 changed files with 2818 additions and 2 deletions

1
.gitignore vendored
View File

@ -44,6 +44,7 @@ snapshot.sh
tests/go_gen
tests/monsterdata_java_wire.mon
tests/monsterdata_go_wire.mon
tests/monsterdata_javascript_wire.mon
CMakeLists.txt.user
CMakeScripts/**
CTestTestfile.cmake

View File

@ -33,6 +33,7 @@ set(FlatBuffers_Compiler_SRCS
src/idl_gen_cpp.cpp
src/idl_gen_general.cpp
src/idl_gen_go.cpp
src/idl_gen_js.cpp
src/idl_gen_python.cpp
src/idl_gen_fbs.cpp
src/flatc.cpp

View File

@ -449,6 +449,7 @@ extern void GenComment(const std::vector<std::string> &dc,
// Container of options that may apply to any of the source/text generators.
struct GeneratorOptions {
bool strict_json;
bool skip_js_exports;
bool output_default_scalars_in_json;
int indent_step;
bool output_enum_identifiers;
@ -464,6 +465,7 @@ struct GeneratorOptions {
Language lang;
GeneratorOptions() : strict_json(false),
skip_js_exports(false),
output_default_scalars_in_json(false),
indent_step(2),
output_enum_identifiers(true), prefixed_enums(true), scoped_enums(false),
@ -506,6 +508,15 @@ extern bool GenerateCPP(const Parser &parser,
const std::string &file_name,
const GeneratorOptions &opts);
// Generate JavaScript code from the definitions in the Parser object.
// See idl_gen_js.
extern std::string GenerateJS(const Parser &parser,
const GeneratorOptions &opts);
extern bool GenerateJS(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
// Generate Go files from the definitions in the Parser object.
// See idl_gen_go.cpp.
extern bool GenerateGo(const Parser &parser,
@ -551,6 +562,13 @@ extern bool GenerateFBS(const Parser &parser,
const std::string &file_name,
const GeneratorOptions &opts);
// Generate a make rule for the generated JavaScript code.
// See idl_gen_js.cpp.
extern std::string JSMakeRule(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
// Generate a make rule for the generated C++ header.
// See idl_gen_cpp.cpp.
extern std::string CPPMakeRule(const Parser &parser,

1021
js/flatbuffers.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -60,6 +60,10 @@ const Generator generators[] = {
flatbuffers::GeneratorOptions::kJava,
"Generate Java classes for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateJS, "-s", "JavaScript",
flatbuffers::GeneratorOptions::kMAX,
"Generate JavaScript code for tables/structs",
flatbuffers::JSMakeRule },
{ flatbuffers::GenerateGeneral, "-n", "C#",
flatbuffers::GeneratorOptions::kCSharp,
"Generate C# classes for tables/structs",
@ -140,6 +144,8 @@ int main(int argc, const char *argv[]) {
include_directories.push_back(argv[argi]);
} else if(arg == "--strict-json") {
opts.strict_json = true;
} else if(arg == "--no-js-exports") {
opts.skip_js_exports = true;
} else if(arg == "--defaults-json") {
opts.output_default_scalars_in_json = true;
} else if(arg == "--no-prefix") {

712
src/idl_gen_js.cpp Normal file
View File

@ -0,0 +1,712 @@
/*
* Copyright 2014 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// independent from idl_parser, since this code is not needed for most clients
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
namespace flatbuffers {
namespace js {
static void GenNamespaces(const Parser &parser, std::string *code_ptr,
std::string *exports_ptr) {
std::set<std::string> namespaces;
for (auto it = parser.namespaces_.begin();
it != parser.namespaces_.end(); ++it) {
std::string namespace_so_far;
// Gather all parent namespaces for this namespace
for (auto component = (*it)->components.begin();
component != (*it)->components.end(); ++component) {
if (!namespace_so_far.empty()) {
namespace_so_far += '.';
}
namespace_so_far += *component;
namespaces.insert(namespace_so_far);
}
}
// Make sure parent namespaces come before child namespaces
std::vector<std::string> sorted_namespaces(
namespaces.begin(), namespaces.end());
std::sort(sorted_namespaces.begin(), sorted_namespaces.end());
// Emit namespaces in a form that Closure Compiler can optimize
std::string &code = *code_ptr;
std::string &exports = *exports_ptr;
for (auto it = sorted_namespaces.begin();
it != sorted_namespaces.end(); it++) {
code += "/**\n * @const\n*/\n";
if (it->find('.') == std::string::npos) {
code += "var ";
exports += "this." + *it + " = " + *it + ";\n";
}
code += *it + " = " + *it + " || {};\n\n";
}
}
// Ensure that a type is prefixed with its namespace whenever it is used
// outside of its namespace.
static std::string WrapInNameSpace(const Namespace *ns,
const std::string &name) {
std::string qualified_name;
for (auto it = ns->components.begin();
it != ns->components.end(); ++it) {
qualified_name += *it + ".";
}
return qualified_name + name;
}
static std::string WrapInNameSpace(const Definition &def) {
return WrapInNameSpace(def.defined_namespace, def.name);
}
// Generate a documentation comment, if available.
static void GenDocComment(const std::vector<std::string> &dc,
std::string *code_ptr,
const std::string &extra_lines,
const char *indent = nullptr) {
if (dc.empty() && extra_lines.empty()) {
// Don't output empty comment blocks with 0 lines of comment content.
return;
}
std::string &code = *code_ptr;
if (indent) code += indent;
code += "/**\n";
for (auto it = dc.begin(); it != dc.end(); ++it) {
if (indent) code += indent;
code += " *" + *it + "\n";
}
if (!extra_lines.empty()) {
if (!dc.empty()) {
if (indent) code += indent;
code += " *\n";
}
if (indent) code += indent;
std::string::size_type start = 0;
while (true) {
auto end = extra_lines.find('\n', start);
if (end != std::string::npos) {
code += " * " + extra_lines.substr(start, end - start) + "\n";
start = end + 1;
} else {
code += " * " + extra_lines.substr(start) + "\n";
break;
}
}
}
if (indent) code += indent;
code += " */\n";
}
static void GenDocComment(std::string *code_ptr,
const std::string &extra_lines) {
GenDocComment(std::vector<std::string>(), code_ptr, extra_lines);
}
// Generate an enum declaration and an enum string lookup table.
static void GenEnum(EnumDef &enum_def, std::string *code_ptr,
std::string *exports_ptr) {
if (enum_def.generated) return;
std::string &code = *code_ptr;
std::string &exports = *exports_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";
}
code += WrapInNameSpace(enum_def) + " = {\n";
for (auto it = enum_def.vals.vec.begin();
it != enum_def.vals.vec.end(); ++it) {
auto &ev = **it;
if (!ev.doc_comment.empty()) {
if (it != enum_def.vals.vec.begin()) {
code += '\n';
}
GenDocComment(ev.doc_comment, code_ptr, "", " ");
}
code += " " + ev.name + ": " + NumToString(ev.value);
code += (it + 1) != enum_def.vals.vec.end() ? ",\n" : "\n";
}
code += "};\n\n";
}
static std::string GenType(const Type &type) {
switch (type.base_type) {
case BASE_TYPE_BOOL:
case BASE_TYPE_CHAR: return "Int8";
case BASE_TYPE_UTYPE:
case BASE_TYPE_UCHAR: return "Uint8";
case BASE_TYPE_SHORT: return "Int16";
case BASE_TYPE_USHORT: return "Uint16";
case BASE_TYPE_INT: return "Int32";
case BASE_TYPE_UINT: return "Uint32";
case BASE_TYPE_LONG: return "Int64";
case BASE_TYPE_ULONG: return "Uint64";
case BASE_TYPE_FLOAT: return "Float32";
case BASE_TYPE_DOUBLE: return "Float64";
case BASE_TYPE_STRING: return "String";
case BASE_TYPE_VECTOR: return GenType(type.VectorType());
case BASE_TYPE_STRUCT: return type.struct_def->name;
default: return "Table";
}
}
static std::string GenGetter(const Type &type, const std::string &arguments) {
switch (type.base_type) {
case BASE_TYPE_STRING: return "this.bb.__string" + arguments;
case BASE_TYPE_STRUCT: return "this.bb.__struct" + arguments;
case BASE_TYPE_UNION: return "this.bb.__union" + arguments;
case BASE_TYPE_VECTOR: return GenGetter(type.VectorType(), arguments);
default: {
auto getter = "this.bb.read" + MakeCamel(GenType(type)) + arguments;
if (type.base_type == BASE_TYPE_BOOL) {
getter = "!!" + getter;
}
if (type.enum_def) {
getter = "/** @type {" + WrapInNameSpace(*type.enum_def) + "} */ (" +
getter + ")";
}
return getter;
}
}
}
static std::string GenDefaultValue(const Value &value) {
if (value.type.enum_def) {
if (auto val = value.type.enum_def->ReverseLookup(
atoi(value.constant.c_str()), false)) {
return WrapInNameSpace(*value.type.enum_def) + "." + val->name;
}
}
switch (value.type.base_type) {
case BASE_TYPE_BOOL:
return value.constant == "0" ? "false" : "true";
case BASE_TYPE_STRING:
return "null";
case BASE_TYPE_LONG:
case BASE_TYPE_ULONG:
if (value.constant != "0") {
int64_t constant = std::atoll(value.constant.c_str());
return "new flatbuffers.Long(" + NumToString((int32_t)constant) +
", " + NumToString((int32_t)(constant >> 32)) + ")";
}
return "flatbuffers.Long.ZERO";
default:
return value.constant;
}
}
enum struct InOut {
IN,
OUT,
};
static std::string GenTypeName(const Type &type, InOut inOut) {
if (inOut == InOut::OUT) {
if (type.base_type == BASE_TYPE_STRING) {
return "?string";
}
if (type.base_type == BASE_TYPE_STRUCT) {
return WrapInNameSpace(*type.struct_def);
}
}
switch (type.base_type) {
case BASE_TYPE_BOOL: return "boolean";
case BASE_TYPE_LONG:
case BASE_TYPE_ULONG: return "flatbuffers.Long";
default:
if (IsScalar(type.base_type)) {
if (type.enum_def) {
return WrapInNameSpace(*type.enum_def);
}
return "number";
}
return "flatbuffers.Offset";
}
}
// Returns the method name for use with add/put calls.
static std::string GenWriteMethod(const Type &type) {
// Forward to signed versions since unsigned versions don't exist
switch (type.base_type) {
case BASE_TYPE_UTYPE:
case BASE_TYPE_UCHAR: return GenWriteMethod(Type(BASE_TYPE_CHAR));
case BASE_TYPE_USHORT: return GenWriteMethod(Type(BASE_TYPE_SHORT));
case BASE_TYPE_UINT: return GenWriteMethod(Type(BASE_TYPE_INT));
case BASE_TYPE_ULONG: return GenWriteMethod(Type(BASE_TYPE_LONG));
default: break;
}
return IsScalar(type.base_type)
? MakeCamel(GenType(type))
: (IsStruct(type) ? "Struct" : "Offset");
}
template <typename T>
static std::string MaybeAdd(T value) {
return value != 0 ? " + " + NumToString(value) : "";
}
template <typename T>
static std::string MaybeScale(T value) {
return value != 1 ? " * " + NumToString(value) : "";
}
static void GenStructArgs(const StructDef &struct_def,
std::string *annotations,
std::string *arguments,
const std::string &nameprefix) {
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (IsStruct(field.value.type)) {
// Generate arguments for a struct inside a struct. To ensure names
// don't clash, and to make it obvious these arguments are constructing
// a nested struct, prefix the name with the field name.
GenStructArgs(*field.value.type.struct_def, annotations, arguments,
nameprefix + field.name + "_");
} else {
*annotations += "@param {" + GenTypeName(field.value.type, InOut::IN);
*annotations += "} " + nameprefix + field.name + "\n";
*arguments += ", " + nameprefix + field.name;
}
}
}
static void GenStructBody(const StructDef &struct_def,
std::string *body,
const std::string &nameprefix) {
*body += " builder.prep(";
*body += NumToString(struct_def.minalign) + ", ";
*body += NumToString(struct_def.bytesize) + ");\n";
for (auto it = struct_def.fields.vec.rbegin();
it != struct_def.fields.vec.rend(); ++it) {
auto &field = **it;
if (field.padding) {
*body += " builder.pad(" + NumToString(field.padding) + ");\n";
}
if (IsStruct(field.value.type)) {
// Generate arguments for a struct inside a struct. To ensure names
// don't clash, and to make it obvious these arguments are constructing
// a nested struct, prefix the name with the field name.
GenStructBody(*field.value.type.struct_def, body,
nameprefix + field.name + "_");
} else {
*body += " builder.write" + GenWriteMethod(field.value.type) + "(";
if (field.value.type.base_type == BASE_TYPE_BOOL) {
*body += "+";
}
*body += nameprefix + field.name + ");\n";
}
}
}
// Generate an accessor struct with constructor for a flatbuffers struct.
static void GenStruct(const Parser &parser, StructDef &struct_def,
std::string *code_ptr, std::string *exports_ptr) {
if (struct_def.generated) return;
std::string &code = *code_ptr;
std::string &exports = *exports_ptr;
// Emit constructor
bool isStatement = struct_def.defined_namespace->components.empty();
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";
code += "function " + object_name;
} else {
code += object_name + " = function";
}
code += "() {\n";
code += " /**\n";
code += " * @type {flatbuffers.ByteBuffer}\n";
code += " */\n";
code += " this.bb = null;\n";
code += "\n";
code += " /**\n";
code += " * @type {number}\n";
code += " */\n";
code += " this.bb_pos = 0;\n";
code += isStatement ? "}\n\n" : "};\n\n";
// Generate the __init method that sets the field in a pre-existing
// accessor object. This is to allow object reuse.
code += "/**\n";
code += " * @param {number} i\n";
code += " * @param {flatbuffers.ByteBuffer} bb\n";
code += " * @returns {" + object_name + "}\n";
code += " */\n";
code += object_name + ".prototype.__init = function(i, bb) {\n";
code += " this.bb_pos = i;\n";
code += " this.bb = bb;\n";
code += " return this;\n";
code += "};\n\n";
// Generate a special accessor for the table that when used as the root of a
// FlatBuffer
if (!struct_def.fixed) {
GenDocComment(code_ptr,
"@param {flatbuffers.ByteBuffer} bb\n"
"@param {" + object_name + "=} obj\n"
"@returns {" + object_name + "}");
code += object_name + ".getRootAs" + struct_def.name;
code += " = function(bb, obj) {\n";
code += " return (obj || new " + object_name;
code += ").__init(bb.readInt32(bb.position()) + bb.position(), bb);\n";
code += "};\n\n";
// Generate the identifier check method
if (parser.root_struct_def_ == &struct_def &&
!parser.file_identifier_.empty()) {
GenDocComment(code_ptr,
"@param {flatbuffers.ByteBuffer} bb\n"
"@returns {boolean}");
code += object_name + ".bufferHasIdentifier = function(bb) {\n";
code += " return bb.__has_identifier('" + parser.file_identifier_;
code += "');\n};\n\n";
}
}
// Emit field accessors
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
auto offset_prefix = " var offset = this.bb.__offset(this.bb_pos, " +
NumToString(field.value.offset) + ");\n return offset ? ";
// Emit a scalar field
if (IsScalar(field.value.type.base_type) ||
field.value.type.base_type == BASE_TYPE_STRING) {
GenDocComment(field.doc_comment, code_ptr,
"@returns {" + GenTypeName(field.value.type, InOut::OUT) + "}");
code += object_name + ".prototype." + MakeCamel(field.name, false);
code += " = function() {\n";
if (struct_def.fixed) {
code += " return " + GenGetter(field.value.type, "(this.bb_pos" +
MaybeAdd(field.value.offset) + ")") + ";\n";
} else {
code += offset_prefix + GenGetter(field.value.type,
"(this.bb_pos + offset)") + " : " + GenDefaultValue(field.value);
code += ";\n";
}
}
// Emit an object field
else {
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
auto type = WrapInNameSpace(*field.value.type.struct_def);
GenDocComment(field.doc_comment, code_ptr,
"@param {" + type + "=} obj\n@returns {" + type + "}");
code += object_name + ".prototype." + MakeCamel(field.name, false);
code += " = function(obj) {\n";
if (struct_def.fixed) {
code += " return (obj || new " + type;
code += ").__init(this.bb_pos";
code += MaybeAdd(field.value.offset) + ", this.bb);\n";
} else {
code += offset_prefix + "(obj || new " + type + ").__init(";
code += field.value.type.struct_def->fixed
? "this.bb_pos + offset"
: "this.bb.__indirect(this.bb_pos + offset)";
code += ", this.bb) : null;\n";
}
break;
}
case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType();
auto vectortypename = GenTypeName(vectortype, InOut::OUT);
auto inline_size = InlineSize(vectortype);
auto index = "this.bb.__vector(this.bb_pos + offset) + index" +
MaybeScale(inline_size);
GenDocComment(field.doc_comment, code_ptr,
"@param {number} index\n" +
std::string(vectortype.base_type == BASE_TYPE_STRUCT ?
"@param {" + vectortypename + "=} obj\n" :
"") +
"@returns {" + vectortypename + "}");
code += object_name + ".prototype." + MakeCamel(field.name, false);
code += " = function(index";
if (vectortype.base_type == BASE_TYPE_STRUCT) {
code += ", obj";
}
code += ") {\n";
if (vectortype.base_type == BASE_TYPE_STRUCT) {
code += offset_prefix + "(obj || new " + vectortypename;
code += ").__init(";
code += vectortype.struct_def->fixed
? index
: "this.bb.__indirect(" + index + ")";
code += ", this.bb)";
} else {
code += offset_prefix + GenGetter(vectortype, "(" + index + ")");
}
code += " : ";
if (field.value.type.element == BASE_TYPE_BOOL) {
code += "false";
} else if (field.value.type.element == BASE_TYPE_LONG ||
field.value.type.element == BASE_TYPE_ULONG) {
code += "flatbuffers.Long.ZERO";
} else if (IsScalar(field.value.type.element)) {
code += "0";
} else {
code += "null";
}
code += ";\n";
break;
}
case BASE_TYPE_UNION:
GenDocComment(field.doc_comment, code_ptr,
"@param {flatbuffers.Table} obj\n"
"@returns {?flatbuffers.Table}");
code += object_name + ".prototype." + MakeCamel(field.name, false);
code += " = function(obj) {\n";
code += offset_prefix + GenGetter(field.value.type,
"(obj, this.bb_pos + offset)") + " : null;\n";
break;
default:
assert(0);
}
}
code += "};\n\n";
// Emit a length helper
if (field.value.type.base_type == BASE_TYPE_VECTOR) {
GenDocComment(code_ptr, "@returns {number}");
code += object_name + ".prototype." + MakeCamel(field.name, false);
code += "Length = function() {\n" + offset_prefix;
code += "this.bb.__vector_len(this.bb_pos + offset) : 0;\n};\n\n";
}
}
// Emit a factory constructor
if (struct_def.fixed) {
std::string annotations = "@param {flatbuffers.Builder} builder\n";
std::string arguments;
GenStructArgs(struct_def, &annotations, &arguments, "");
GenDocComment(code_ptr, annotations +
"@returns {flatbuffers.Offset}");
code += object_name + ".create" + struct_def.name + " = function(builder";
code += arguments + ") {\n";
GenStructBody(struct_def, &code, "");
code += " return builder.offset();\n};\n\n";
} else {
// Generate a method to start building a new object
GenDocComment(code_ptr,
"@param {flatbuffers.Builder} builder");
code += object_name + ".start" + struct_def.name;
code += " = function(builder) {\n";
code += " builder.startObject(" + NumToString(
struct_def.fields.vec.size()) + ");\n";
code += "};\n\n";
// Generate a set of static methods that allow table construction
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
auto argname = MakeCamel(field.name, false);
if (!IsScalar(field.value.type.base_type)) {
argname += "Offset";
}
// Generate the field insertion method
GenDocComment(code_ptr,
"@param {flatbuffers.Builder} builder\n"
"@param {" + GenTypeName(field.value.type, InOut::IN) + "} " +
argname);
code += object_name + ".add" + MakeCamel(field.name);
code += " = function(builder, " + argname + ") {\n";
code += " builder.addField" + GenWriteMethod(field.value.type) + "(";
code += NumToString(it - struct_def.fields.vec.begin()) + ", ";
if (field.value.type.base_type == BASE_TYPE_BOOL) {
code += "+";
}
code += argname + ", ";
if (!IsScalar(field.value.type.base_type)) {
code += "0";
} else {
if (field.value.type.base_type == BASE_TYPE_BOOL) {
code += "+";
}
code += GenDefaultValue(field.value);
}
code += ");\n};\n\n";
if (field.value.type.base_type == BASE_TYPE_VECTOR) {
auto vector_type = field.value.type.VectorType();
auto alignment = InlineAlignment(vector_type);
auto elem_size = InlineSize(vector_type);
// Generate a method to create a vector from a JavaScript array
if (!IsStruct(vector_type)) {
GenDocComment(code_ptr,
"@param {flatbuffers.Builder} builder\n"
"@param {Array.<" + GenTypeName(vector_type, InOut::IN) +
">} data\n"
"@returns {flatbuffers.Offset}");
code += object_name + ".create" + MakeCamel(field.name);
code += "Vector = function(builder, data) {\n";
code += " builder.startVector(" + NumToString(elem_size);
code += ", data.length, " + NumToString(alignment) + ");\n";
code += " for (var i = data.length - 1; i >= 0; i--) {\n";
code += " builder.add" + GenWriteMethod(vector_type);
code += "(data[i]);\n";
code += " }\n";
code += " return builder.endVector();\n";
code += "};\n\n";
}
// Generate a method to start a vector, data to be added manually after
GenDocComment(code_ptr,
"@param {flatbuffers.Builder} builder\n"
"@param {number} numElems");
code += object_name + ".start" + MakeCamel(field.name);
code += "Vector = function(builder, numElems) {\n";
code += " builder.startVector(" + NumToString(elem_size);
code += ", numElems, " + NumToString(alignment) + ");\n";
code += "};\n\n";
}
}
// Generate a method to stop building a new object
GenDocComment(code_ptr,
"@param {flatbuffers.Builder} builder\n"
"@returns {flatbuffers.Offset}");
code += object_name + ".end" + struct_def.name;
code += " = function(builder) {\n";
code += " var offset = builder.endObject();\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (!field.deprecated && field.required) {
code += " builder.requiredField(offset, ";
code += NumToString(field.value.offset);
code += "); // " + field.name + "\n";
}
}
code += " return offset;\n";
code += "};\n\n";
// Generate the method to complete buffer construction
if (parser.root_struct_def_ == &struct_def) {
GenDocComment(code_ptr,
"@param {flatbuffers.Builder} builder\n"
"@param {flatbuffers.Offset} offset");
code += object_name + ".finish" + struct_def.name + "Buffer";
code += " = function(builder, offset) {\n";
code += " return builder.finish(offset";
if (!parser.file_identifier_.empty()) {
code += ", '" + parser.file_identifier_ + "'";
}
code += ");\n";
code += "};\n\n";
}
}
}
} // namespace js
// Iterate through all definitions we haven't generate code for (enums, structs,
// and tables) and output them to a single file.
std::string GenerateJS(const Parser &parser,
const GeneratorOptions &opts) {
using namespace js;
// Generate code for all the enum declarations.
std::string enum_code, exports_code;
for (auto it = parser.enums_.vec.begin();
it != parser.enums_.vec.end(); ++it) {
GenEnum(**it, &enum_code, &exports_code);
}
// Generate code for all structs, then all tables.
std::string decl_code;
for (auto it = parser.structs_.vec.begin();
it != parser.structs_.vec.end(); ++it) {
GenStruct(parser, **it, &decl_code, &exports_code);
}
// Only output file-level code if there were any declarations.
if (enum_code.length() || decl_code.length()) {
std::string code;
code = "// automatically generated by the FlatBuffers compiler,"
" do not modify\n\n";
// Generate code for all the namespace declarations.
GenNamespaces(parser, &code, &exports_code);
// Output the main declaration code from above.
code += enum_code;
code += decl_code;
if (!exports_code.empty() && !opts.skip_js_exports) {
code += "// Exports for Node.js and RequireJS\n";
code += exports_code;
}
return code;
}
return std::string();
}
static std::string GeneratedFileName(const std::string &path,
const std::string &file_name) {
return path + file_name + "_generated.js";
}
bool GenerateJS(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts) {
auto code = GenerateJS(parser, opts);
return !code.length() ||
SaveFile(GeneratedFileName(path, file_name).c_str(), code, false);
}
std::string JSMakeRule(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions & /*opts*/) {
std::string filebase = flatbuffers::StripPath(
flatbuffers::StripExtension(file_name));
std::string make_rule = GeneratedFileName(path, filebase) + ": ";
auto included_files = parser.GetIncludedFilesRecursive(file_name);
for (auto it = included_files.begin();
it != included_files.end(); ++it) {
make_rule += " " + *it;
}
return make_rule;
}
} // namespace flatbuffers

116
tests/JavaScriptTest.js Normal file
View File

@ -0,0 +1,116 @@
var assert = require('assert');
var fs = require('fs');
var flatbuffers = require('../js/flatbuffers').flatbuffers;
var MyGame = require('./monster_test_generated').MyGame;
function main() {
// First, let's test reading a FlatBuffer generated by C++ code:
// This file was generated from monsterdata_test.json
var data = new Uint8Array(fs.readFileSync('monsterdata_test.mon'));
// Now test it:
var bb = new flatbuffers.ByteBuffer(data);
testBuffer(bb);
// Second, let's create a FlatBuffer from scratch in JavaScript, and test it also.
// We use an initial size of 1 to exercise the reallocation algorithm,
// normally a size larger than the typical FlatBuffer you generate would be
// better for performance.
var fbb = new flatbuffers.Builder(1);
// We set up the same values as monsterdata.json:
var str = fbb.createString('MyMonster');
var inv = MyGame.Example.Monster.createInventoryVector(fbb, [0, 1, 2, 3, 4]);
var fred = fbb.createString('Fred');
MyGame.Example.Monster.startMonster(fbb);
MyGame.Example.Monster.addName(fbb, fred);
var mon2 = MyGame.Example.Monster.endMonster(fbb);
MyGame.Example.Monster.startTest4Vector(fbb, 2);
MyGame.Example.Test.createTest(fbb, 10, 20);
MyGame.Example.Test.createTest(fbb, 30, 40);
var test4 = fbb.endVector();
var testArrayOfString = MyGame.Example.Monster.createTestarrayofstringVector(fbb, [
fbb.createString('test1'),
fbb.createString('test2')
]);
MyGame.Example.Monster.startMonster(fbb);
MyGame.Example.Monster.addPos(fbb, MyGame.Example.Vec3.createVec3(fbb, 1, 2, 3, 3, MyGame.Example.Color.Green, 5, 6));
MyGame.Example.Monster.addHp(fbb, 80);
MyGame.Example.Monster.addName(fbb, str);
MyGame.Example.Monster.addInventory(fbb, inv);
MyGame.Example.Monster.addTestType(fbb, MyGame.Example.Any.Monster);
MyGame.Example.Monster.addTest(fbb, mon2);
MyGame.Example.Monster.addTest4(fbb, test4);
MyGame.Example.Monster.addTestarrayofstring(fbb, testArrayOfString);
MyGame.Example.Monster.addTestbool(fbb, false);
var mon = MyGame.Example.Monster.endMonster(fbb);
MyGame.Example.Monster.finishMonsterBuffer(fbb, mon);
// Write the result to a file for debugging purposes:
// Note that the binaries are not necessarily identical, since the JSON
// parser may serialize in a slightly different order than the above
// JavaScript code. They are functionally equivalent though.
fs.writeFileSync('monsterdata_javascript_wire.mon', new Buffer(fbb.asUint8Array()));
// Test it:
testBuffer(fbb.dataBuffer());
console.log('FlatBuffers test: completed successfully');
}
function testBuffer(bb) {
assert.ok(MyGame.Example.Monster.bufferHasIdentifier(bb));
var monster = MyGame.Example.Monster.getRootAsMonster(bb);
assert.strictEqual(monster.hp(), 80);
assert.strictEqual(monster.mana(), 150); // default
assert.strictEqual(monster.name(), 'MyMonster');
var pos = monster.pos();
assert.strictEqual(pos.x(), 1);
assert.strictEqual(pos.y(), 2);
assert.strictEqual(pos.z(), 3);
assert.strictEqual(pos.test1(), 3);
assert.strictEqual(pos.test2(), MyGame.Example.Color.Green);
var t = pos.test3();
assert.strictEqual(t.a(), 5);
assert.strictEqual(t.b(), 6);
assert.strictEqual(monster.testType(), MyGame.Example.Any.Monster);
var monster2 = new MyGame.Example.Monster();
assert.strictEqual(monster.test(monster2) != null, true);
assert.strictEqual(monster2.name(), 'Fred');
assert.strictEqual(monster.inventoryLength(), 5);
var invsum = 0;
for (var i = 0; i < monster.inventoryLength(); i++) {
invsum += monster.inventory(i);
}
assert.strictEqual(invsum, 10);
var test_0 = monster.test4(0);
var test_1 = monster.test4(1);
assert.strictEqual(monster.test4Length(), 2);
assert.strictEqual(test_0.a() + test_0.b() + test_1.a() + test_1.b(), 100);
assert.strictEqual(monster.testarrayofstringLength(), 2);
assert.strictEqual(monster.testarrayofstring(0), 'test1');
assert.strictEqual(monster.testarrayofstring(1), 'test2');
assert.strictEqual(monster.testbool(), false);
}
main();

5
tests/JavaScriptTest.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
pushd "$(dirname $0)" >/dev/null
test_dir="$(pwd)"
node ${test_dir}/JavaScriptTest

View File

@ -1,2 +1,2 @@
../flatc -c -j -n -g -b -p --gen-mutable --no-includes monster_test.fbs monsterdata_test.json
../flatc -c -j -n -g -b -p -s --gen-mutable --no-includes monster_test.fbs monsterdata_test.json
../flatc -b --schema monster_test.fbs

View File

@ -0,0 +1,936 @@
// automatically generated by the FlatBuffers compiler, do not modify
/**
* @const
*/
var MyGame = MyGame || {};
/**
* @const
*/
MyGame.Example = MyGame.Example || {};
/**
* @const
*/
MyGame.OtherNameSpace = MyGame.OtherNameSpace || {};
/**
* @enum
*/
MyGame.Example.Color = {
Red: 1,
Green: 2,
Blue: 8
};
/**
* @enum
*/
MyGame.Example.Any = {
NONE: 0,
Monster: 1,
TestSimpleTableWithEnum: 2
};
/**
* @constructor
*/
MyGame.Example.Test = function() {
/**
* @type {flatbuffers.ByteBuffer}
*/
this.bb = null;
/**
* @type {number}
*/
this.bb_pos = 0;
};
/**
* @param {number} i
* @param {flatbuffers.ByteBuffer} bb
* @returns {MyGame.Example.Test}
*/
MyGame.Example.Test.prototype.__init = function(i, bb) {
this.bb_pos = i;
this.bb = bb;
return this;
};
/**
* @returns {number}
*/
MyGame.Example.Test.prototype.a = function() {
return this.bb.readInt16(this.bb_pos);
};
/**
* @returns {number}
*/
MyGame.Example.Test.prototype.b = function() {
return this.bb.readInt8(this.bb_pos + 2);
};
/**
* @param {flatbuffers.Builder} builder
* @param {number} a
* @param {number} b
* @returns {flatbuffers.Offset}
*/
MyGame.Example.Test.createTest = function(builder, a, b) {
builder.prep(2, 4);
builder.pad(1);
builder.writeInt8(b);
builder.writeInt16(a);
return builder.offset();
};
/**
* @constructor
*/
MyGame.Example.TestSimpleTableWithEnum = function() {
/**
* @type {flatbuffers.ByteBuffer}
*/
this.bb = null;
/**
* @type {number}
*/
this.bb_pos = 0;
};
/**
* @param {number} i
* @param {flatbuffers.ByteBuffer} bb
* @returns {MyGame.Example.TestSimpleTableWithEnum}
*/
MyGame.Example.TestSimpleTableWithEnum.prototype.__init = function(i, bb) {
this.bb_pos = i;
this.bb = bb;
return this;
};
/**
* @param {flatbuffers.ByteBuffer} bb
* @param {MyGame.Example.TestSimpleTableWithEnum=} obj
* @returns {MyGame.Example.TestSimpleTableWithEnum}
*/
MyGame.Example.TestSimpleTableWithEnum.getRootAsTestSimpleTableWithEnum = function(bb, obj) {
return (obj || new MyGame.Example.TestSimpleTableWithEnum).__init(bb.readInt32(bb.position()) + bb.position(), bb);
};
/**
* @returns {MyGame.Example.Color}
*/
MyGame.Example.TestSimpleTableWithEnum.prototype.color = function() {
var offset = this.bb.__offset(this.bb_pos, 4);
return offset ? /** @type {MyGame.Example.Color} */ (this.bb.readInt8(this.bb_pos + offset)) : MyGame.Example.Color.Green;
};
/**
* @param {flatbuffers.Builder} builder
*/
MyGame.Example.TestSimpleTableWithEnum.startTestSimpleTableWithEnum = function(builder) {
builder.startObject(1);
};
/**
* @param {flatbuffers.Builder} builder
* @param {MyGame.Example.Color} color
*/
MyGame.Example.TestSimpleTableWithEnum.addColor = function(builder, color) {
builder.addFieldInt8(0, color, MyGame.Example.Color.Green);
};
/**
* @param {flatbuffers.Builder} builder
* @returns {flatbuffers.Offset}
*/
MyGame.Example.TestSimpleTableWithEnum.endTestSimpleTableWithEnum = function(builder) {
var offset = builder.endObject();
return offset;
};
/**
* @constructor
*/
MyGame.Example.Vec3 = function() {
/**
* @type {flatbuffers.ByteBuffer}
*/
this.bb = null;
/**
* @type {number}
*/
this.bb_pos = 0;
};
/**
* @param {number} i
* @param {flatbuffers.ByteBuffer} bb
* @returns {MyGame.Example.Vec3}
*/
MyGame.Example.Vec3.prototype.__init = function(i, bb) {
this.bb_pos = i;
this.bb = bb;
return this;
};
/**
* @returns {number}
*/
MyGame.Example.Vec3.prototype.x = function() {
return this.bb.readFloat32(this.bb_pos);
};
/**
* @returns {number}
*/
MyGame.Example.Vec3.prototype.y = function() {
return this.bb.readFloat32(this.bb_pos + 4);
};
/**
* @returns {number}
*/
MyGame.Example.Vec3.prototype.z = function() {
return this.bb.readFloat32(this.bb_pos + 8);
};
/**
* @returns {number}
*/
MyGame.Example.Vec3.prototype.test1 = function() {
return this.bb.readFloat64(this.bb_pos + 16);
};
/**
* @returns {MyGame.Example.Color}
*/
MyGame.Example.Vec3.prototype.test2 = function() {
return /** @type {MyGame.Example.Color} */ (this.bb.readInt8(this.bb_pos + 24));
};
/**
* @param {MyGame.Example.Test=} obj
* @returns {MyGame.Example.Test}
*/
MyGame.Example.Vec3.prototype.test3 = function(obj) {
return (obj || new MyGame.Example.Test).__init(this.bb_pos + 26, this.bb);
};
/**
* @param {flatbuffers.Builder} builder
* @param {number} x
* @param {number} y
* @param {number} z
* @param {number} test1
* @param {MyGame.Example.Color} test2
* @param {number} test3_a
* @param {number} test3_b
* @returns {flatbuffers.Offset}
*/
MyGame.Example.Vec3.createVec3 = function(builder, x, y, z, test1, test2, test3_a, test3_b) {
builder.prep(16, 32);
builder.pad(2);
builder.prep(2, 4);
builder.pad(1);
builder.writeInt8(test3_b);
builder.writeInt16(test3_a);
builder.pad(1);
builder.writeInt8(test2);
builder.writeFloat64(test1);
builder.pad(4);
builder.writeFloat32(z);
builder.writeFloat32(y);
builder.writeFloat32(x);
return builder.offset();
};
/**
* @constructor
*/
MyGame.Example.Stat = function() {
/**
* @type {flatbuffers.ByteBuffer}
*/
this.bb = null;
/**
* @type {number}
*/
this.bb_pos = 0;
};
/**
* @param {number} i
* @param {flatbuffers.ByteBuffer} bb
* @returns {MyGame.Example.Stat}
*/
MyGame.Example.Stat.prototype.__init = function(i, bb) {
this.bb_pos = i;
this.bb = bb;
return this;
};
/**
* @param {flatbuffers.ByteBuffer} bb
* @param {MyGame.Example.Stat=} obj
* @returns {MyGame.Example.Stat}
*/
MyGame.Example.Stat.getRootAsStat = function(bb, obj) {
return (obj || new MyGame.Example.Stat).__init(bb.readInt32(bb.position()) + bb.position(), bb);
};
/**
* @returns {?string}
*/
MyGame.Example.Stat.prototype.id = function() {
var offset = this.bb.__offset(this.bb_pos, 4);
return offset ? this.bb.__string(this.bb_pos + offset) : null;
};
/**
* @returns {flatbuffers.Long}
*/
MyGame.Example.Stat.prototype.val = function() {
var offset = this.bb.__offset(this.bb_pos, 6);
return offset ? this.bb.readInt64(this.bb_pos + offset) : flatbuffers.Long.ZERO;
};
/**
* @returns {number}
*/
MyGame.Example.Stat.prototype.count = function() {
var offset = this.bb.__offset(this.bb_pos, 8);
return offset ? this.bb.readUint16(this.bb_pos + offset) : 0;
};
/**
* @param {flatbuffers.Builder} builder
*/
MyGame.Example.Stat.startStat = function(builder) {
builder.startObject(3);
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Offset} idOffset
*/
MyGame.Example.Stat.addId = function(builder, idOffset) {
builder.addFieldOffset(0, idOffset, 0);
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Long} val
*/
MyGame.Example.Stat.addVal = function(builder, val) {
builder.addFieldInt64(1, val, flatbuffers.Long.ZERO);
};
/**
* @param {flatbuffers.Builder} builder
* @param {number} count
*/
MyGame.Example.Stat.addCount = function(builder, count) {
builder.addFieldInt16(2, count, 0);
};
/**
* @param {flatbuffers.Builder} builder
* @returns {flatbuffers.Offset}
*/
MyGame.Example.Stat.endStat = function(builder) {
var offset = builder.endObject();
return offset;
};
/**
* @constructor
*/
MyGame.Example.Monster = function() {
/**
* @type {flatbuffers.ByteBuffer}
*/
this.bb = null;
/**
* @type {number}
*/
this.bb_pos = 0;
};
/**
* @param {number} i
* @param {flatbuffers.ByteBuffer} bb
* @returns {MyGame.Example.Monster}
*/
MyGame.Example.Monster.prototype.__init = function(i, bb) {
this.bb_pos = i;
this.bb = bb;
return this;
};
/**
* @param {flatbuffers.ByteBuffer} bb
* @param {MyGame.Example.Monster=} obj
* @returns {MyGame.Example.Monster}
*/
MyGame.Example.Monster.getRootAsMonster = function(bb, obj) {
return (obj || new MyGame.Example.Monster).__init(bb.readInt32(bb.position()) + bb.position(), bb);
};
/**
* @param {flatbuffers.ByteBuffer} bb
* @returns {boolean}
*/
MyGame.Example.Monster.bufferHasIdentifier = function(bb) {
return bb.__has_identifier('MONS');
};
/**
* @param {MyGame.Example.Vec3=} obj
* @returns {MyGame.Example.Vec3}
*/
MyGame.Example.Monster.prototype.pos = function(obj) {
var offset = this.bb.__offset(this.bb_pos, 4);
return offset ? (obj || new MyGame.Example.Vec3).__init(this.bb_pos + offset, this.bb) : null;
};
/**
* @returns {number}
*/
MyGame.Example.Monster.prototype.mana = function() {
var offset = this.bb.__offset(this.bb_pos, 6);
return offset ? this.bb.readInt16(this.bb_pos + offset) : 150;
};
/**
* @returns {number}
*/
MyGame.Example.Monster.prototype.hp = function() {
var offset = this.bb.__offset(this.bb_pos, 8);
return offset ? this.bb.readInt16(this.bb_pos + offset) : 100;
};
/**
* @returns {?string}
*/
MyGame.Example.Monster.prototype.name = function() {
var offset = this.bb.__offset(this.bb_pos, 10);
return offset ? this.bb.__string(this.bb_pos + offset) : null;
};
/**
* @param {number} index
* @returns {number}
*/
MyGame.Example.Monster.prototype.inventory = function(index) {
var offset = this.bb.__offset(this.bb_pos, 14);
return offset ? this.bb.readUint8(this.bb.__vector(this.bb_pos + offset) + index) : 0;
};
/**
* @returns {number}
*/
MyGame.Example.Monster.prototype.inventoryLength = function() {
var offset = this.bb.__offset(this.bb_pos, 14);
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
};
/**
* @returns {MyGame.Example.Color}
*/
MyGame.Example.Monster.prototype.color = function() {
var offset = this.bb.__offset(this.bb_pos, 16);
return offset ? /** @type {MyGame.Example.Color} */ (this.bb.readInt8(this.bb_pos + offset)) : MyGame.Example.Color.Blue;
};
/**
* @returns {MyGame.Example.Any}
*/
MyGame.Example.Monster.prototype.testType = function() {
var offset = this.bb.__offset(this.bb_pos, 18);
return offset ? /** @type {MyGame.Example.Any} */ (this.bb.readUint8(this.bb_pos + offset)) : MyGame.Example.Any.NONE;
};
/**
* @param {flatbuffers.Table} obj
* @returns {?flatbuffers.Table}
*/
MyGame.Example.Monster.prototype.test = function(obj) {
var offset = this.bb.__offset(this.bb_pos, 20);
return offset ? this.bb.__union(obj, this.bb_pos + offset) : null;
};
/**
* @param {number} index
* @param {MyGame.Example.Test=} obj
* @returns {MyGame.Example.Test}
*/
MyGame.Example.Monster.prototype.test4 = function(index, obj) {
var offset = this.bb.__offset(this.bb_pos, 22);
return offset ? (obj || new MyGame.Example.Test).__init(this.bb.__vector(this.bb_pos + offset) + index * 4, this.bb) : null;
};
/**
* @returns {number}
*/
MyGame.Example.Monster.prototype.test4Length = function() {
var offset = this.bb.__offset(this.bb_pos, 22);
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
};
/**
* @param {number} index
* @returns {?string}
*/
MyGame.Example.Monster.prototype.testarrayofstring = function(index) {
var offset = this.bb.__offset(this.bb_pos, 24);
return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4) : null;
};
/**
* @returns {number}
*/
MyGame.Example.Monster.prototype.testarrayofstringLength = function() {
var offset = this.bb.__offset(this.bb_pos, 24);
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
};
/**
* an example documentation comment: this will end up in the generated code
* multiline too
*
* @param {number} index
* @param {MyGame.Example.Monster=} obj
* @returns {MyGame.Example.Monster}
*/
MyGame.Example.Monster.prototype.testarrayoftables = function(index, obj) {
var offset = this.bb.__offset(this.bb_pos, 26);
return offset ? (obj || new MyGame.Example.Monster).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null;
};
/**
* @returns {number}
*/
MyGame.Example.Monster.prototype.testarrayoftablesLength = function() {
var offset = this.bb.__offset(this.bb_pos, 26);
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
};
/**
* @param {MyGame.Example.Monster=} obj
* @returns {MyGame.Example.Monster}
*/
MyGame.Example.Monster.prototype.enemy = function(obj) {
var offset = this.bb.__offset(this.bb_pos, 28);
return offset ? (obj || new MyGame.Example.Monster).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null;
};
/**
* @param {number} index
* @returns {number}
*/
MyGame.Example.Monster.prototype.testnestedflatbuffer = function(index) {
var offset = this.bb.__offset(this.bb_pos, 30);
return offset ? this.bb.readUint8(this.bb.__vector(this.bb_pos + offset) + index) : 0;
};
/**
* @returns {number}
*/
MyGame.Example.Monster.prototype.testnestedflatbufferLength = function() {
var offset = this.bb.__offset(this.bb_pos, 30);
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
};
/**
* @param {MyGame.Example.Stat=} obj
* @returns {MyGame.Example.Stat}
*/
MyGame.Example.Monster.prototype.testempty = function(obj) {
var offset = this.bb.__offset(this.bb_pos, 32);
return offset ? (obj || new MyGame.Example.Stat).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null;
};
/**
* @returns {boolean}
*/
MyGame.Example.Monster.prototype.testbool = function() {
var offset = this.bb.__offset(this.bb_pos, 34);
return offset ? !!this.bb.readInt8(this.bb_pos + offset) : false;
};
/**
* @returns {number}
*/
MyGame.Example.Monster.prototype.testhashs32Fnv1 = function() {
var offset = this.bb.__offset(this.bb_pos, 36);
return offset ? this.bb.readInt32(this.bb_pos + offset) : 0;
};
/**
* @returns {number}
*/
MyGame.Example.Monster.prototype.testhashu32Fnv1 = function() {
var offset = this.bb.__offset(this.bb_pos, 38);
return offset ? this.bb.readUint32(this.bb_pos + offset) : 0;
};
/**
* @returns {flatbuffers.Long}
*/
MyGame.Example.Monster.prototype.testhashs64Fnv1 = function() {
var offset = this.bb.__offset(this.bb_pos, 40);
return offset ? this.bb.readInt64(this.bb_pos + offset) : flatbuffers.Long.ZERO;
};
/**
* @returns {flatbuffers.Long}
*/
MyGame.Example.Monster.prototype.testhashu64Fnv1 = function() {
var offset = this.bb.__offset(this.bb_pos, 42);
return offset ? this.bb.readUint64(this.bb_pos + offset) : flatbuffers.Long.ZERO;
};
/**
* @returns {number}
*/
MyGame.Example.Monster.prototype.testhashs32Fnv1a = function() {
var offset = this.bb.__offset(this.bb_pos, 44);
return offset ? this.bb.readInt32(this.bb_pos + offset) : 0;
};
/**
* @returns {number}
*/
MyGame.Example.Monster.prototype.testhashu32Fnv1a = function() {
var offset = this.bb.__offset(this.bb_pos, 46);
return offset ? this.bb.readUint32(this.bb_pos + offset) : 0;
};
/**
* @returns {flatbuffers.Long}
*/
MyGame.Example.Monster.prototype.testhashs64Fnv1a = function() {
var offset = this.bb.__offset(this.bb_pos, 48);
return offset ? this.bb.readInt64(this.bb_pos + offset) : flatbuffers.Long.ZERO;
};
/**
* @returns {flatbuffers.Long}
*/
MyGame.Example.Monster.prototype.testhashu64Fnv1a = function() {
var offset = this.bb.__offset(this.bb_pos, 50);
return offset ? this.bb.readUint64(this.bb_pos + offset) : flatbuffers.Long.ZERO;
};
/**
* @param {flatbuffers.Builder} builder
*/
MyGame.Example.Monster.startMonster = function(builder) {
builder.startObject(24);
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Offset} posOffset
*/
MyGame.Example.Monster.addPos = function(builder, posOffset) {
builder.addFieldStruct(0, posOffset, 0);
};
/**
* @param {flatbuffers.Builder} builder
* @param {number} mana
*/
MyGame.Example.Monster.addMana = function(builder, mana) {
builder.addFieldInt16(1, mana, 150);
};
/**
* @param {flatbuffers.Builder} builder
* @param {number} hp
*/
MyGame.Example.Monster.addHp = function(builder, hp) {
builder.addFieldInt16(2, hp, 100);
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Offset} nameOffset
*/
MyGame.Example.Monster.addName = function(builder, nameOffset) {
builder.addFieldOffset(3, nameOffset, 0);
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Offset} inventoryOffset
*/
MyGame.Example.Monster.addInventory = function(builder, inventoryOffset) {
builder.addFieldOffset(5, inventoryOffset, 0);
};
/**
* @param {flatbuffers.Builder} builder
* @param {Array.<number>} data
* @returns {flatbuffers.Offset}
*/
MyGame.Example.Monster.createInventoryVector = function(builder, data) {
builder.startVector(1, data.length, 1);
for (var i = data.length - 1; i >= 0; i--) {
builder.addInt8(data[i]);
}
return builder.endVector();
};
/**
* @param {flatbuffers.Builder} builder
* @param {number} numElems
*/
MyGame.Example.Monster.startInventoryVector = function(builder, numElems) {
builder.startVector(1, numElems, 1);
};
/**
* @param {flatbuffers.Builder} builder
* @param {MyGame.Example.Color} color
*/
MyGame.Example.Monster.addColor = function(builder, color) {
builder.addFieldInt8(6, color, MyGame.Example.Color.Blue);
};
/**
* @param {flatbuffers.Builder} builder
* @param {MyGame.Example.Any} testType
*/
MyGame.Example.Monster.addTestType = function(builder, testType) {
builder.addFieldInt8(7, testType, MyGame.Example.Any.NONE);
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Offset} testOffset
*/
MyGame.Example.Monster.addTest = function(builder, testOffset) {
builder.addFieldOffset(8, testOffset, 0);
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Offset} test4Offset
*/
MyGame.Example.Monster.addTest4 = function(builder, test4Offset) {
builder.addFieldOffset(9, test4Offset, 0);
};
/**
* @param {flatbuffers.Builder} builder
* @param {number} numElems
*/
MyGame.Example.Monster.startTest4Vector = function(builder, numElems) {
builder.startVector(4, numElems, 2);
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Offset} testarrayofstringOffset
*/
MyGame.Example.Monster.addTestarrayofstring = function(builder, testarrayofstringOffset) {
builder.addFieldOffset(10, testarrayofstringOffset, 0);
};
/**
* @param {flatbuffers.Builder} builder
* @param {Array.<flatbuffers.Offset>} data
* @returns {flatbuffers.Offset}
*/
MyGame.Example.Monster.createTestarrayofstringVector = function(builder, data) {
builder.startVector(4, data.length, 4);
for (var i = data.length - 1; i >= 0; i--) {
builder.addOffset(data[i]);
}
return builder.endVector();
};
/**
* @param {flatbuffers.Builder} builder
* @param {number} numElems
*/
MyGame.Example.Monster.startTestarrayofstringVector = function(builder, numElems) {
builder.startVector(4, numElems, 4);
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Offset} testarrayoftablesOffset
*/
MyGame.Example.Monster.addTestarrayoftables = function(builder, testarrayoftablesOffset) {
builder.addFieldOffset(11, testarrayoftablesOffset, 0);
};
/**
* @param {flatbuffers.Builder} builder
* @param {Array.<flatbuffers.Offset>} data
* @returns {flatbuffers.Offset}
*/
MyGame.Example.Monster.createTestarrayoftablesVector = function(builder, data) {
builder.startVector(4, data.length, 4);
for (var i = data.length - 1; i >= 0; i--) {
builder.addOffset(data[i]);
}
return builder.endVector();
};
/**
* @param {flatbuffers.Builder} builder
* @param {number} numElems
*/
MyGame.Example.Monster.startTestarrayoftablesVector = function(builder, numElems) {
builder.startVector(4, numElems, 4);
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Offset} enemyOffset
*/
MyGame.Example.Monster.addEnemy = function(builder, enemyOffset) {
builder.addFieldOffset(12, enemyOffset, 0);
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Offset} testnestedflatbufferOffset
*/
MyGame.Example.Monster.addTestnestedflatbuffer = function(builder, testnestedflatbufferOffset) {
builder.addFieldOffset(13, testnestedflatbufferOffset, 0);
};
/**
* @param {flatbuffers.Builder} builder
* @param {Array.<number>} data
* @returns {flatbuffers.Offset}
*/
MyGame.Example.Monster.createTestnestedflatbufferVector = function(builder, data) {
builder.startVector(1, data.length, 1);
for (var i = data.length - 1; i >= 0; i--) {
builder.addInt8(data[i]);
}
return builder.endVector();
};
/**
* @param {flatbuffers.Builder} builder
* @param {number} numElems
*/
MyGame.Example.Monster.startTestnestedflatbufferVector = function(builder, numElems) {
builder.startVector(1, numElems, 1);
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Offset} testemptyOffset
*/
MyGame.Example.Monster.addTestempty = function(builder, testemptyOffset) {
builder.addFieldOffset(14, testemptyOffset, 0);
};
/**
* @param {flatbuffers.Builder} builder
* @param {boolean} testbool
*/
MyGame.Example.Monster.addTestbool = function(builder, testbool) {
builder.addFieldInt8(15, +testbool, +false);
};
/**
* @param {flatbuffers.Builder} builder
* @param {number} testhashs32Fnv1
*/
MyGame.Example.Monster.addTesthashs32Fnv1 = function(builder, testhashs32Fnv1) {
builder.addFieldInt32(16, testhashs32Fnv1, 0);
};
/**
* @param {flatbuffers.Builder} builder
* @param {number} testhashu32Fnv1
*/
MyGame.Example.Monster.addTesthashu32Fnv1 = function(builder, testhashu32Fnv1) {
builder.addFieldInt32(17, testhashu32Fnv1, 0);
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Long} testhashs64Fnv1
*/
MyGame.Example.Monster.addTesthashs64Fnv1 = function(builder, testhashs64Fnv1) {
builder.addFieldInt64(18, testhashs64Fnv1, flatbuffers.Long.ZERO);
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Long} testhashu64Fnv1
*/
MyGame.Example.Monster.addTesthashu64Fnv1 = function(builder, testhashu64Fnv1) {
builder.addFieldInt64(19, testhashu64Fnv1, flatbuffers.Long.ZERO);
};
/**
* @param {flatbuffers.Builder} builder
* @param {number} testhashs32Fnv1a
*/
MyGame.Example.Monster.addTesthashs32Fnv1a = function(builder, testhashs32Fnv1a) {
builder.addFieldInt32(20, testhashs32Fnv1a, 0);
};
/**
* @param {flatbuffers.Builder} builder
* @param {number} testhashu32Fnv1a
*/
MyGame.Example.Monster.addTesthashu32Fnv1a = function(builder, testhashu32Fnv1a) {
builder.addFieldInt32(21, testhashu32Fnv1a, 0);
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Long} testhashs64Fnv1a
*/
MyGame.Example.Monster.addTesthashs64Fnv1a = function(builder, testhashs64Fnv1a) {
builder.addFieldInt64(22, testhashs64Fnv1a, flatbuffers.Long.ZERO);
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Long} testhashu64Fnv1a
*/
MyGame.Example.Monster.addTesthashu64Fnv1a = function(builder, testhashu64Fnv1a) {
builder.addFieldInt64(23, testhashu64Fnv1a, flatbuffers.Long.ZERO);
};
/**
* @param {flatbuffers.Builder} builder
* @returns {flatbuffers.Offset}
*/
MyGame.Example.Monster.endMonster = function(builder) {
var offset = builder.endObject();
builder.requiredField(offset, 10); // name
return offset;
};
/**
* @param {flatbuffers.Builder} builder
* @param {flatbuffers.Offset} offset
*/
MyGame.Example.Monster.finishMonsterBuffer = function(builder, offset) {
return builder.finish(offset, 'MONS');
};
// Exports for Node.js and RequireJS
this.MyGame = MyGame;