Squashed 'third_party/flatbuffers/' changes from bc44fad35..8aa8b9139
8aa8b9139 Fix handling of +/-inf defaults in TS/rust/go/dart codegen (#7588)
001adf782 Add support for parsing proto map fields (#7613)
dbc58ab77 Fix help output for --gen-includes (#7611)
2facfeec7 Fix missing spaces in flatc help text (#7612)
4de2814c7 Fix: arduino platform build (#7625)
37b1acdaf Fix current official name of macOS (#7627)
a22434e2a Add missing #include <algorithm> for std::min/std::max uses, and #include <limits> for std::numeric_limits<> (#7624)
214cc9468 Bump Rust version to 22.10.26 before publication (#7622)
a4ff275d9 Added option to not requires an EoF token when parsing JSON (#7620)
15f32c690 python: object generation prefix and suffix (#7565)
051afd882 Add CreateSharedString to python builder (#7608)
728c033ad Add check for presence of realpath to CMakeLists.txt to support more platforms (#7603)
4c514483d Update DartTest.sh golden files (#7606)
c2d9c2080 [TS] Add support for fixed length arrays on Typescript (#5864) (#7021) (#7581)
e34ae4c6b `build.yml`: Fix missing 'v' in version
e54536127 `build.yml` Update to Kotlin Wrapper 1.0.5
49d9f941c `release.yml` Use env var for passphrase
cefc21c1f `release.yml` Add GPG key for Maven
3e64fa724 `release.yml`: Add Maven Steps
b15f3c57e `release_yml` Use new dotnet version
ff802c680 `release.yml` Use NuGet Key directly
b401957d5 `release.yml` Changed Push to follow examples
8c8151f8f `release.yml` Fix nuget push command
ebb7c203d `release.yml` Add Nuget support
203241ed3 FlatBuffers Version 22.10.26 (#7607)
ac485609c `setup.py`: Define version directly
de5b85aa6 `release.yml`: Switch to `python` directory
de3df2d88 `release.yml`: Add publishing to PyPi
043a24f2e [Python] Fixed the issue with nested unions relying on InitFromBuf. (#7576)
5a48b0d7d release.yml: Typo
ce307556f release.yml: Remove `npm ci`
cb616e27c Create release.yml (#7605)
a54ca1e75 FlatBuffers Version 22.10.25 (#7604)
5b3fadcc1 [vector] Allow to iterate with mutables (#7586)
872a49746 [Nim] Bfbs Nim Generator (#7534)
e30170296 Make type conversions explicit. (#7595)
f7b734438 Fix LongEnum definitions (#7596)
5792623df Rust fix compilation for no_std targets #2 (#7553)
0edb27528 Update Rust version (#7574)
acc6a20d3 tests/test.cpp contains a couple of tests that are only executed (#7571)
04cd037ba Fix #7580 by documenting union schema evolution rules (#7585)
e1c5db988 Turn on clippy for Rust and fix lints for non-generated code (#7575)
b80142b90 Update documentation to mention enum value attributes (#7570)
54418f371 Add support for metadata attributes for enum values (#7567) (#7568)
c92e78a9f FlatBuffers Version 22.9.29 (#7557)
d243b904c [TS] Make strict compliant and improve typings (#7549)
374f8fb5f Rust soundness fixes (#7518)
dadbff571 Moves swift package to root of repository so it can be used directly … (#7548)
76ddae006 FlatBuffers Version 22.9.24 (#7547)
cfe157ec5 Emit internal enums when swift_implementation_only (#7545)
413115858 [Python] Python fixed size array (#7529)
88046190e Upgrade grpc to 1.49.0 and make sure it builds (#7538)
72aa85a75 [C++] Rare bad buffer content alignment if sizeof(T) != alignof(T) (#7520)
bfceebb7f Fix conform (#7532)
git-subtree-dir: third_party/flatbuffers
git-subtree-split: 8aa8b9139eb330f27816a5b8b5bbef402fbe3632
Signed-off-by: James Kuszmaul <james.kuszmaul@bluerivertech.com>
Change-Id: I943faba499baf58e9f561b1e4734922188ba8626
diff --git a/src/idl_gen_ts.cpp b/src/idl_gen_ts.cpp
index 32ab863..9fd1203 100644
--- a/src/idl_gen_ts.cpp
+++ b/src/idl_gen_ts.cpp
@@ -16,6 +16,7 @@
#include <algorithm>
#include <cassert>
+#include <cmath>
#include <unordered_map>
#include <unordered_set>
@@ -402,12 +403,26 @@
const auto &value = field.value;
if (value.type.enum_def && value.type.base_type != BASE_TYPE_UNION &&
value.type.base_type != BASE_TYPE_VECTOR) {
- // If the value is an enum with a 64-bit base type, we have to just
- // return the bigint value directly since typescript does not support
- // enums with bigint backing types.
switch (value.type.base_type) {
+ case BASE_TYPE_ARRAY: {
+ std::string ret = "[";
+ for (auto i = 0; i < value.type.fixed_length; ++i) {
+ std::string enum_name =
+ AddImport(imports, *value.type.enum_def, *value.type.enum_def)
+ .name;
+ std::string enum_value = namer_.Variant(
+ *value.type.enum_def->FindByValue(value.constant));
+ ret += enum_name + "." + enum_value +
+ (i < value.type.fixed_length - 1 ? ", " : "");
+ }
+ ret += "]";
+ return ret;
+ }
case BASE_TYPE_LONG:
case BASE_TYPE_ULONG: {
+ // If the value is an enum with a 64-bit base type, we have to just
+ // return the bigint value directly since typescript does not support
+ // enums with bigint backing types.
return "BigInt('" + value.constant + "')";
}
default: {
@@ -432,6 +447,7 @@
return "null";
}
+ case BASE_TYPE_ARRAY:
case BASE_TYPE_VECTOR: return "[]";
case BASE_TYPE_LONG:
@@ -439,9 +455,16 @@
return "BigInt('" + value.constant + "')";
}
- default:
- if (value.constant == "nan") { return "NaN"; }
+ default: {
+ if (StringIsFlatbufferNan(value.constant)) {
+ return "NaN";
+ } else if (StringIsFlatbufferPositiveInfinity(value.constant)) {
+ return "Infinity";
+ } else if (StringIsFlatbufferNegativeInfinity(value.constant)) {
+ return "-Infinity";
+ }
return value.constant;
+ }
}
}
@@ -464,6 +487,22 @@
case BASE_TYPE_BOOL: return allowNull ? "boolean|null" : "boolean";
case BASE_TYPE_LONG:
case BASE_TYPE_ULONG: return allowNull ? "bigint|null" : "bigint";
+ case BASE_TYPE_ARRAY: {
+ std::string name;
+ if (type.element == BASE_TYPE_LONG || type.element == BASE_TYPE_ULONG) {
+ name = "bigint[]";
+ } else if (type.element != BASE_TYPE_STRUCT) {
+ name = "number[]";
+ } else {
+ name = "any[]";
+ if (parser_.opts.generate_object_based_api) {
+ name = "(any|" +
+ GetTypeName(*type.struct_def, /*object_api =*/true) + ")[]";
+ }
+ }
+
+ return name + (allowNull ? "|null" : "");
+ }
default:
if (IsScalar(type.base_type)) {
if (type.enum_def) {
@@ -536,12 +575,91 @@
// 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 + "_");
+ GenStructBody(
+ *field.value.type.struct_def, body,
+ nameprefix.length() ? nameprefix + "_" + field.name : 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";
+ auto element_type = field.value.type.element;
+
+ if (field.value.type.base_type == BASE_TYPE_ARRAY) {
+ switch (field.value.type.element) {
+ case BASE_TYPE_STRUCT: {
+ std::string str_last_item_idx =
+ NumToString(field.value.type.fixed_length - 1);
+ *body += "\n for (let i = " + str_last_item_idx +
+ "; i >= 0; --i" + ") {\n";
+
+ std::string fname = nameprefix.length()
+ ? nameprefix + "_" + field.name
+ : field.name;
+
+ *body += " const item = " + fname + "?.[i];\n\n";
+
+ if (parser_.opts.generate_object_based_api) {
+ *body += " if (item instanceof " +
+ GetTypeName(*field.value.type.struct_def,
+ /*object_api =*/true) +
+ ") {\n";
+ *body += " item.pack(builder);\n";
+ *body += " continue;\n";
+ *body += " }\n\n";
+ }
+
+ std::string class_name =
+ GetPrefixedName(*field.value.type.struct_def);
+ std::string pack_func_create_call =
+ class_name + ".create" + class_name + "(builder,\n";
+ pack_func_create_call +=
+ " " +
+ GenStructMemberValueTS(*field.value.type.struct_def, "item",
+ ",\n ", false) +
+ "\n ";
+ *body += " " + pack_func_create_call;
+ *body += " );\n }\n\n";
+
+ break;
+ }
+ default: {
+ std::string str_last_item_idx =
+ NumToString(field.value.type.fixed_length - 1);
+ std::string fname = nameprefix.length()
+ ? nameprefix + "_" + field.name
+ : field.name;
+
+ *body += "\n for (let i = " + str_last_item_idx +
+ "; i >= 0; --i) {\n";
+ *body += " builder.write";
+ *body += GenWriteMethod(
+ static_cast<flatbuffers::Type>(field.value.type.element));
+ *body += "(";
+ *body += element_type == BASE_TYPE_BOOL ? "+" : "";
+
+ if (element_type == BASE_TYPE_LONG ||
+ element_type == BASE_TYPE_ULONG) {
+ *body += "BigInt(" + fname + "?.[i] ?? 0));\n";
+ } else {
+ *body += "(" + fname + "?.[i] ?? 0));\n\n";
+ }
+ *body += " }\n\n";
+ break;
+ }
+ }
+ } else {
+ std::string fname =
+ nameprefix.length() ? nameprefix + "_" + field.name : field.name;
+
+ *body += " builder.write" + GenWriteMethod(field.value.type) + "(";
+ if (field.value.type.base_type == BASE_TYPE_BOOL) {
+ *body += "Number(Boolean(" + fname + ")));\n";
+ continue;
+ } else if (field.value.type.base_type == BASE_TYPE_LONG ||
+ field.value.type.base_type == BASE_TYPE_ULONG) {
+ *body += "BigInt(" + fname + " ?? 0));\n";
+ continue;
+ }
+
+ *body += fname + ");\n";
+ }
}
}
}
@@ -759,10 +877,10 @@
import.object_name = object_name;
import.bare_file_path = bare_file_path;
import.rel_file_path = rel_file_path;
- import.import_statement =
- "import { " + symbols_expression + " } from '" + rel_file_path + ".js';";
- import.export_statement =
- "export { " + symbols_expression + " } from '." + bare_file_path + ".js';";
+ import.import_statement = "import { " + symbols_expression + " } from '" +
+ rel_file_path + ".js';";
+ import.export_statement = "export { " + symbols_expression + " } from '." +
+ bare_file_path + ".js';";
import.dependency = &dependency;
import.dependent = &dependent;
@@ -903,7 +1021,7 @@
const auto conversion_function = GenUnionConvFuncName(enum_def);
ret = "(() => {\n";
- ret += " let temp = " + conversion_function + "(this." +
+ ret += " const temp = " + conversion_function + "(this." +
namer_.Method(field_name, "Type") + "(), " +
field_binded_method + ");\n";
ret += " if(temp === null) { return null; }\n";
@@ -916,17 +1034,20 @@
const auto conversion_function = GenUnionListConvFuncName(enum_def);
ret = "(() => {\n";
- ret += " let ret = [];\n";
+ ret += " const ret: (" +
+ GenObjApiUnionTypeTS(imports, *union_type.struct_def,
+ parser_.opts, *union_type.enum_def) +
+ ")[] = [];\n";
ret += " for(let targetEnumIndex = 0; targetEnumIndex < this." +
namer_.Method(field_name, "TypeLength") + "()" +
"; "
"++targetEnumIndex) {\n";
- ret += " let targetEnum = this." +
+ ret += " const targetEnum = this." +
namer_.Method(field_name, "Type") + "(targetEnumIndex);\n";
ret += " if(targetEnum === null || " + enum_type +
"[targetEnum!] === 'NONE') { "
"continue; }\n\n";
- ret += " let temp = " + conversion_function + "(targetEnum, " +
+ ret += " const temp = " + conversion_function + "(targetEnum, " +
field_binded_method + ", targetEnumIndex);\n";
ret += " if(temp === null) { continue; }\n";
ret += union_has_string ? " if(typeof temp === 'string') { "
@@ -973,6 +1094,11 @@
std::string nullValue = "0";
if (field.value.type.base_type == BASE_TYPE_BOOL) {
nullValue = "false";
+ } else if (field.value.type.base_type == BASE_TYPE_LONG ||
+ field.value.type.base_type == BASE_TYPE_ULONG) {
+ nullValue = "BigInt(0)";
+ } else if (field.value.type.base_type == BASE_TYPE_ARRAY) {
+ nullValue = "[]";
}
ret += "(" + curr_member_accessor + " ?? " + nullValue + ")";
} else {
@@ -1091,7 +1217,7 @@
break;
}
- case BASE_TYPE_VECTOR: {
+ case BASE_TYPE_ARRAY: {
auto vectortype = field.value.type.VectorType();
auto vectortypename =
GenTypeName(imports, struct_def, vectortype, false);
@@ -1102,13 +1228,15 @@
switch (vectortype.base_type) {
case BASE_TYPE_STRUCT: {
const auto &sd = *field.value.type.struct_def;
- field_type += GetTypeName(sd, /*object_api=*/true);
- ;
+ const auto field_type_name =
+ GetTypeName(sd, /*object_api=*/true);
+ field_type += field_type_name;
field_type += ")[]";
- field_val = GenBBAccess() + ".createObjList(" +
- field_binded_method + ", this." +
- namer_.Method(field, "Length") + "())";
+ field_val = GenBBAccess() + ".createObjList<" + vectortypename +
+ ", " + field_type_name + ">(" +
+ field_binded_method + ", " +
+ NumToString(field.value.type.fixed_length) + ")";
if (sd.fixed) {
field_offset_decl =
@@ -1128,7 +1256,7 @@
case BASE_TYPE_STRING: {
field_type += "string)[]";
- field_val = GenBBAccess() + ".createScalarList(" +
+ field_val = GenBBAccess() + ".createScalarList<string>(" +
field_binded_method + ", this." +
namer_.Field(field, "Length") + "())";
field_offset_decl =
@@ -1162,10 +1290,99 @@
field_type += vectortypename;
}
field_type += ")[]";
- field_val = GenBBAccess() + ".createScalarList(" +
+ field_val = GenBBAccess() + ".createScalarList<" +
+ vectortypename + ">(" + field_binded_method + ", " +
+ NumToString(field.value.type.fixed_length) + ")";
+
+ field_offset_decl =
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, this." + field_field + ")";
+
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case BASE_TYPE_VECTOR: {
+ auto vectortype = field.value.type.VectorType();
+ auto vectortypename =
+ GenTypeName(imports, struct_def, vectortype, false);
+ is_vector = true;
+
+ field_type = "(";
+
+ switch (vectortype.base_type) {
+ case BASE_TYPE_STRUCT: {
+ const auto &sd = *field.value.type.struct_def;
+ const auto field_type_name =
+ GetTypeName(sd, /*object_api=*/true);
+ field_type += field_type_name;
+ field_type += ")[]";
+
+ field_val = GenBBAccess() + ".createObjList<" + vectortypename +
+ ", " + field_type_name + ">(" +
field_binded_method + ", this." +
namer_.Method(field, "Length") + "())";
+ if (sd.fixed) {
+ field_offset_decl =
+ "builder.createStructOffsetList(this." + field_field +
+ ", " + AddImport(imports, struct_def, struct_def).name +
+ "." + namer_.Method("start", field, "Vector") + ")";
+ } else {
+ field_offset_decl =
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ field_field + "))";
+ }
+
+ break;
+ }
+
+ case BASE_TYPE_STRING: {
+ field_type += "string)[]";
+ field_val = GenBBAccess() + ".createScalarList<string>(" +
+ field_binded_method + ", this." +
+ namer_.Field(field, "Length") + "())";
+ field_offset_decl =
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ namer_.Field(field) + "))";
+ break;
+ }
+
+ case BASE_TYPE_UNION: {
+ field_type += GenObjApiUnionTypeTS(
+ imports, struct_def, parser.opts, *(vectortype.enum_def));
+ field_type += ")[]";
+ field_val = GenUnionValTS(imports, struct_def, field_method,
+ vectortype, true);
+
+ field_offset_decl =
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ namer_.Field(field) + "))";
+
+ break;
+ }
+ default: {
+ if (vectortype.enum_def) {
+ field_type += GenTypeName(imports, struct_def, vectortype,
+ false, HasNullDefault(field));
+ } else {
+ field_type += vectortypename;
+ }
+ field_type += ")[]";
+ field_val = GenBBAccess() + ".createScalarList<" +
+ vectortypename + ">(" + field_binded_method +
+ ", this." + namer_.Method(field, "Length") + "())";
+
field_offset_decl =
AddImport(imports, struct_def, struct_def).name + "." +
namer_.Method("create", field, "Vector") +
@@ -1260,7 +1477,7 @@
obj_api_class = "\n";
obj_api_class += "export class ";
obj_api_class += GetTypeName(struct_def, /*object_api=*/true);
- obj_api_class += " {\n";
+ obj_api_class += " implements flatbuffers.IGeneratedObject {\n";
obj_api_class += constructor_func;
obj_api_class += pack_func_prototype + pack_func_offset_decl +
pack_func_create_call + "\n}";
@@ -1298,12 +1515,17 @@
}
const std::string object_name = GetTypeName(struct_def);
+ const std::string object_api_name = GetTypeName(struct_def, true);
// Emit constructor
GenDocComment(struct_def.doc_comment, code_ptr);
code += "export class ";
code += object_name;
- code += " {\n";
+ if (parser.opts.generate_object_based_api)
+ code += " implements flatbuffers.IUnpackableObject<" + object_api_name +
+ "> {\n";
+ else
+ code += " {\n";
code += " bb: flatbuffers.ByteBuffer|null = null;\n";
code += " bb_pos = 0;\n";
@@ -1337,9 +1559,16 @@
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
- auto offset_prefix =
- " const offset = " + GenBBAccess() + ".__offset(this.bb_pos, " +
- NumToString(field.value.offset) + ");\n return offset ? ";
+ std::string offset_prefix = "";
+
+ if (field.value.type.base_type == BASE_TYPE_ARRAY) {
+ offset_prefix = " return ";
+ } else {
+ offset_prefix = " const offset = " + GenBBAccess() +
+ ".__offset(this.bb_pos, " +
+ NumToString(field.value.offset) + ");\n";
+ offset_prefix += " return offset ? ";
+ }
// Emit a scalar field
const auto is_string = IsString(field.value.type);
@@ -1379,9 +1608,11 @@
} else {
std::string index = "this.bb_pos + offset";
if (is_string) { index += ", optionalEncoding"; }
- code += offset_prefix +
- GenGetter(field.value.type, "(" + index + ")") + " : " +
- GenDefaultValue(field, imports);
+ code +=
+ offset_prefix + GenGetter(field.value.type, "(" + index + ")");
+ if (field.value.type.base_type != BASE_TYPE_ARRAY) {
+ code += " : " + GenDefaultValue(field, imports);
+ }
code += ";\n";
}
}
@@ -1414,6 +1645,95 @@
break;
}
+ case BASE_TYPE_ARRAY: {
+ auto vectortype = field.value.type.VectorType();
+ auto vectortypename =
+ GenTypeName(imports, struct_def, vectortype, false);
+ auto inline_size = InlineSize(vectortype);
+ auto index = "this.bb_pos + " + NumToString(field.value.offset) +
+ " + index" + MaybeScale(inline_size);
+ std::string ret_type;
+ bool is_union = false;
+ switch (vectortype.base_type) {
+ case BASE_TYPE_STRUCT: ret_type = vectortypename; break;
+ case BASE_TYPE_STRING: ret_type = vectortypename; break;
+ case BASE_TYPE_UNION:
+ ret_type = "?flatbuffers.Table";
+ is_union = true;
+ break;
+ default: ret_type = vectortypename;
+ }
+ GenDocComment(field.doc_comment, code_ptr);
+ std::string prefix = namer_.Method(field);
+ // TODO: make it work without any
+ // if (is_union) { prefix += "<T extends flatbuffers.Table>"; }
+ if (is_union) { prefix += ""; }
+ prefix += "(index: number";
+ if (is_union) {
+ const auto union_type =
+ GenUnionGenericTypeTS(*(field.value.type.enum_def));
+
+ vectortypename = union_type;
+ code += prefix + ", obj:" + union_type;
+ } else if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ code += prefix + ", obj?:" + vectortypename;
+ } else if (IsString(vectortype)) {
+ code += prefix + "):string\n";
+ code += prefix + ",optionalEncoding:flatbuffers.Encoding" +
+ "):" + vectortypename + "\n";
+ code += prefix + ",optionalEncoding?:any";
+ } else {
+ code += prefix;
+ }
+ code += "):" + vectortypename + "|null {\n";
+
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ code += offset_prefix + "(obj || " +
+ GenerateNewExpression(vectortypename);
+ code += ").__init(";
+ code += vectortype.struct_def->fixed
+ ? index
+ : GenBBAccess() + ".__indirect(" + index + ")";
+ code += ", " + GenBBAccess() + ")";
+ } else {
+ if (is_union) {
+ index = "obj, " + index;
+ } else if (IsString(vectortype)) {
+ index += ", optionalEncoding";
+ }
+ code += offset_prefix + GenGetter(vectortype, "(" + index + ")");
+ }
+
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_ARRAY: {
+ break;
+ }
+ case BASE_TYPE_BOOL: {
+ code += " : false";
+ break;
+ }
+ case BASE_TYPE_LONG:
+ case BASE_TYPE_ULONG: {
+ code += " : BigInt(0)";
+ break;
+ }
+ default: {
+ if (IsScalar(field.value.type.element)) {
+ if (field.value.type.enum_def) {
+ code += field.value.constant;
+ } else {
+ code += " : 0";
+ }
+ } else {
+ code += ": null";
+ }
+ break;
+ }
+ }
+ code += ";\n";
+ break;
+ }
+
case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType();
auto vectortypename =