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 =