forked from BigfootDev/flatbuffers
Ensure optional arrays, arrays with defaults, and strings with defaults are supported (#8896)
Fixing issues with generated ts/js
This commit is contained in:
@@ -522,7 +522,16 @@ class TsGenerator : public BaseGenerator {
|
||||
case BASE_TYPE_BOOL:
|
||||
return value.constant == "0" ? "false" : "true";
|
||||
|
||||
case BASE_TYPE_STRING:
|
||||
case BASE_TYPE_STRING: {
|
||||
// NOTE: Strings without a default value are parsed as "0" by
|
||||
// the parser, so therefore we have to treat "0" as a null-signifying
|
||||
// value.
|
||||
if (value.constant == "0" || value.constant == "null") {
|
||||
return "null";
|
||||
} else {
|
||||
return "\"" + value.constant + "\"";
|
||||
}
|
||||
}
|
||||
case BASE_TYPE_UNION:
|
||||
case BASE_TYPE_STRUCT: {
|
||||
return null_keyword_;
|
||||
@@ -1334,10 +1343,9 @@ class TsGenerator : public BaseGenerator {
|
||||
// Emit a scalar field
|
||||
const auto is_string = IsString(field.value.type);
|
||||
if (IsScalar(field.value.type.base_type) || is_string) {
|
||||
const auto has_null_default = is_string || HasNullDefault(field);
|
||||
|
||||
field_type += GenTypeName(imports, field, field.value.type, false,
|
||||
has_null_default);
|
||||
field_type +=
|
||||
GenTypeName(imports, field, field.value.type, false,
|
||||
!HasDefaultValue(field) || HasNullDefault(field));
|
||||
field_val = "this." + namer_.Method(field) + "()";
|
||||
|
||||
if (field.value.type.base_type != BASE_TYPE_STRING) {
|
||||
@@ -1731,21 +1739,22 @@ class TsGenerator : public BaseGenerator {
|
||||
offset_prefix = " const offset = " + GenBBAccess() +
|
||||
".__offset(this.bb_pos, " +
|
||||
NumToString(field.value.offset) + ");\n";
|
||||
offset_prefix += " return offset ? ";
|
||||
offset_prefix += " return ";
|
||||
}
|
||||
|
||||
// Emit a scalar field
|
||||
const auto is_string = IsString(field.value.type);
|
||||
if (IsScalar(field.value.type.base_type) || is_string) {
|
||||
const auto has_null_default = is_string || HasNullDefault(field);
|
||||
const auto has_null_default =
|
||||
!field.IsRequired() && !HasDefaultValue(field);
|
||||
|
||||
GenDocComment(field.doc_comment, code_ptr);
|
||||
std::string prefix = namer_.Method(field) + "(";
|
||||
if (is_string) {
|
||||
code += prefix + "):string|" + null_keyword_ + "\n";
|
||||
code += prefix + "):" + (has_null_default ? "string|" + null_keyword_ : "string") + "\n";
|
||||
code +=
|
||||
prefix + "optionalEncoding:flatbuffers.Encoding" + "):" +
|
||||
GenTypeName(imports, struct_def, field.value.type, false, true) +
|
||||
GenTypeName(imports, struct_def, field.value.type, false, has_null_default) +
|
||||
"\n";
|
||||
code += prefix + "optionalEncoding?:any";
|
||||
} else {
|
||||
@@ -1774,9 +1783,16 @@ class TsGenerator : public BaseGenerator {
|
||||
if (is_string) {
|
||||
index += ", optionalEncoding";
|
||||
}
|
||||
code +=
|
||||
offset_prefix + GenGetter(field.value.type, "(" + index + ")");
|
||||
if (field.value.type.base_type != BASE_TYPE_ARRAY) {
|
||||
if (field.IsRequired()) {
|
||||
code +=
|
||||
offset_prefix + GenGetter(field.value.type, "(" + index + ")");
|
||||
;
|
||||
} else {
|
||||
code += offset_prefix + "offset ? " +
|
||||
GenGetter(field.value.type, "(" + index + ")");
|
||||
}
|
||||
if (field.value.type.base_type != BASE_TYPE_ARRAY &&
|
||||
!field.IsRequired()) {
|
||||
code += " : " + GenDefaultValue(field, imports);
|
||||
}
|
||||
code += ";\n";
|
||||
@@ -1801,8 +1817,8 @@ class TsGenerator : public BaseGenerator {
|
||||
code +=
|
||||
MaybeAdd(field.value.offset) + ", " + GenBBAccess() + ");\n";
|
||||
} else {
|
||||
code += offset_prefix + "(obj || " + GenerateNewExpression(type) +
|
||||
").__init(";
|
||||
code += offset_prefix + "offset ? (obj || " +
|
||||
GenerateNewExpression(type) + ").__init(";
|
||||
code += field.value.type.struct_def->fixed
|
||||
? "this.bb_pos + offset"
|
||||
: GenBBAccess() + ".__indirect(this.bb_pos + offset)";
|
||||
@@ -1960,7 +1976,7 @@ class TsGenerator : public BaseGenerator {
|
||||
code += "):" + vectortypename + "|" + null_keyword_ + " {\n";
|
||||
|
||||
if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||
code += offset_prefix + "(obj || " +
|
||||
code += offset_prefix + "offset ? (obj || " +
|
||||
GenerateNewExpression(vectortypename);
|
||||
code += ").__init(";
|
||||
code += vectortype.struct_def->fixed
|
||||
@@ -1973,7 +1989,8 @@ class TsGenerator : public BaseGenerator {
|
||||
} else if (IsString(vectortype)) {
|
||||
index += ", optionalEncoding";
|
||||
}
|
||||
code += offset_prefix + GenGetter(vectortype, "(" + index + ")");
|
||||
code += offset_prefix + "offset ? " +
|
||||
GenGetter(vectortype, "(" + index + ")");
|
||||
}
|
||||
code += " : ";
|
||||
if (field.value.type.element == BASE_TYPE_BOOL) {
|
||||
@@ -2005,7 +2022,7 @@ class TsGenerator : public BaseGenerator {
|
||||
" "
|
||||
"{\n";
|
||||
|
||||
code += offset_prefix +
|
||||
code += offset_prefix + "offset ? " +
|
||||
GenGetter(field.value.type, "(obj, this.bb_pos + offset)") +
|
||||
" : " + null_keyword_ + ";\n";
|
||||
break;
|
||||
@@ -2058,7 +2075,7 @@ class TsGenerator : public BaseGenerator {
|
||||
// Emit a length helper
|
||||
GenDocComment(code_ptr);
|
||||
code += namer_.Method(field, "Length");
|
||||
code += "():number {\n" + offset_prefix;
|
||||
code += "():number {\n" + offset_prefix + "offset ? ";
|
||||
|
||||
code +=
|
||||
GenBBAccess() + ".__vector_len(this.bb_pos + offset) : 0;\n}\n\n";
|
||||
@@ -2069,15 +2086,30 @@ class TsGenerator : public BaseGenerator {
|
||||
GenDocComment(code_ptr);
|
||||
|
||||
code += namer_.Method(field, "Array");
|
||||
code += "():" + GenType(vectorType) + "Array|" + null_keyword_ +
|
||||
" {\n" + offset_prefix;
|
||||
|
||||
code += "new " + GenType(vectorType) + "Array(" + GenBBAccess() +
|
||||
".bytes().buffer, " + GenBBAccess() +
|
||||
".bytes().byteOffset + " + GenBBAccess() +
|
||||
".__vector(this.bb_pos + offset), " + GenBBAccess() +
|
||||
".__vector_len(this.bb_pos + offset)) : " + null_keyword_ +
|
||||
";\n}\n\n";
|
||||
std::string return_type =
|
||||
(field.IsRequired() || HasDefaultValue(field))
|
||||
? "Array"
|
||||
: ("Array|" + null_keyword_);
|
||||
if (field.IsRequired()) {
|
||||
code += "():" + GenType(vectorType) + return_type + " {\n" +
|
||||
offset_prefix + "new " + GenType(vectorType) + "Array(" +
|
||||
GenBBAccess() + ".bytes().buffer, " + GenBBAccess() +
|
||||
".bytes().byteOffset + " + GenBBAccess() +
|
||||
".__vector(this.bb_pos + offset), " + GenBBAccess() +
|
||||
".__vector_len(this.bb_pos + offset));\n}\n\n";
|
||||
} else {
|
||||
std::string value = HasDefaultValue(field)
|
||||
? "new " + GenType(vectorType) + "Array()"
|
||||
: "null";
|
||||
code += "():" + GenType(vectorType) + return_type + " {\n" +
|
||||
offset_prefix + "offset ? new " + GenType(vectorType) +
|
||||
"Array(" + GenBBAccess() + ".bytes().buffer, " +
|
||||
GenBBAccess() + ".bytes().byteOffset + " + GenBBAccess() +
|
||||
".__vector(this.bb_pos + offset), " + GenBBAccess() +
|
||||
".__vector_len(this.bb_pos + offset)) : " + value +
|
||||
";\n}\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2308,6 +2340,34 @@ class TsGenerator : public BaseGenerator {
|
||||
return field.IsOptional() && field.value.constant == "null";
|
||||
}
|
||||
|
||||
static bool HasDefaultValue(const FieldDef& field) {
|
||||
switch (field.value.type.base_type) {
|
||||
// These types can't have defaults
|
||||
case BASE_TYPE_UNION:
|
||||
case BASE_TYPE_STRUCT: {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Arrays always have a default (empty array)
|
||||
case BASE_TYPE_ARRAY:
|
||||
return true;
|
||||
|
||||
// The only supported default for vectors is []
|
||||
case BASE_TYPE_VECTOR:
|
||||
return field.value.constant == "[]";
|
||||
|
||||
// Even strings are presumed to be null-default if the default value is
|
||||
// "0", this is intended behavior.
|
||||
case BASE_TYPE_STRING: {
|
||||
return field.value.constant != "0" && field.value.constant != "null";
|
||||
}
|
||||
|
||||
default: {
|
||||
return field.value.constant != "null";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetArgType(import_set& imports, const Definition& owner,
|
||||
const FieldDef& field, bool allowNull) {
|
||||
return GenTypeName(imports, owner, field.value.type, true,
|
||||
|
||||
@@ -2809,7 +2809,8 @@ bool Parser::SupportsOptionalScalars() const {
|
||||
bool Parser::SupportsDefaultVectorsAndStrings() const {
|
||||
static FLATBUFFERS_CONSTEXPR unsigned long supported_langs =
|
||||
IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kNim |
|
||||
IDLOptions::kCpp | IDLOptions::kBinary | IDLOptions::kJson;
|
||||
IDLOptions::kCpp | IDLOptions::kBinary | IDLOptions::kJson |
|
||||
IDLOptions::kTs;
|
||||
return !(opts.lang_to_generate & ~supported_langs);
|
||||
}
|
||||
|
||||
|
||||
23
tests/even_more_defaults.fbs
Normal file
23
tests/even_more_defaults.fbs
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
enum ABC: int { A, B, C }
|
||||
|
||||
struct EvenMoreStruct {
|
||||
g:[int64:2];
|
||||
}
|
||||
|
||||
table EvenMoreDefaults {
|
||||
str: EvenMoreStruct;
|
||||
ints: [int] = [];
|
||||
floats: [float] = [ ];
|
||||
float_optional: [float];
|
||||
bytes_optional: [ubyte];
|
||||
floats_required: [float] (required);
|
||||
empty_string: string = "";
|
||||
some_string: string = "some";
|
||||
zero_string: string = "0";
|
||||
a_string:string (key);
|
||||
required_string: string (required);
|
||||
abcs: [ABC] = [];
|
||||
bools: [bool] = [];
|
||||
one_bool: bool = true;
|
||||
}
|
||||
@@ -87,6 +87,20 @@ flatc(
|
||||
)
|
||||
esbuild("monster_test.ts", "monster_test_generated.cjs")
|
||||
|
||||
flatc(
|
||||
options=[
|
||||
"--ts",
|
||||
"--reflect-names",
|
||||
"--gen-name-strings",
|
||||
"--gen-mutable",
|
||||
"--gen-object-api",
|
||||
"--ts-entry-points",
|
||||
"--ts-flat-files",
|
||||
],
|
||||
schema="../even_more_defaults.fbs",
|
||||
include="../include_test",
|
||||
)
|
||||
|
||||
flatc(
|
||||
options=["--gen-object-api", "-b"],
|
||||
schema="../monster_test.fbs",
|
||||
|
||||
@@ -81,11 +81,11 @@ mutate_hp(value:number):boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
name():string|null
|
||||
name(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
name(optionalEncoding?:any):string|Uint8Array|null {
|
||||
name():string
|
||||
name(optionalEncoding:flatbuffers.Encoding):string|Uint8Array
|
||||
name(optionalEncoding?:any):string|Uint8Array {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 10);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
return this.bb!.__string(this.bb_pos + offset, optionalEncoding);
|
||||
}
|
||||
|
||||
inventory(index: number):number|null {
|
||||
|
||||
Reference in New Issue
Block a user