Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TS] Add support for fixed length arrays on Typescript (#5864) (#7021) #7581

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Expand Up @@ -149,4 +149,4 @@ flatbuffers.pc
**/html/**
**/latex/**
# https://cmake.org/cmake/help/latest/module/FetchContent.html#variable:FETCHCONTENT_BASE_DIR
_deps/
_deps/
335 changes: 320 additions & 15 deletions src/idl_gen_ts.cpp

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/idl_parser.cpp
Expand Up @@ -2581,7 +2581,7 @@ bool Parser::SupportsAdvancedArrayFeatures() const {
return (opts.lang_to_generate &
~(IDLOptions::kCpp | IDLOptions::kPython | IDLOptions::kJava |
IDLOptions::kCSharp | IDLOptions::kJsonSchema | IDLOptions::kJson |
IDLOptions::kBinary | IDLOptions::kRust)) == 0;
IDLOptions::kBinary | IDLOptions::kRust | IDLOptions::kTs)) == 0;
}

Namespace *Parser::UniqueNamespace(Namespace *ns) {
Expand Down
129 changes: 129 additions & 0 deletions tests/ts/JavaScriptComplexArraysTest.js
@@ -0,0 +1,129 @@
/* global BigInt */

import assert from 'assert';
import { readFileSync, writeFileSync } from 'fs';
import * as flatbuffers from 'flatbuffers';
import {
ArrayStructT,
ArrayTable,
ArrayTableT,
InnerStructT,
NestedStructT,
OuterStructT,
TestEnum,
} from './arrays_test_complex/arrays_test_complex_generated.js';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
BigInt.prototype.toJSON = function () {
return this.toString();
};
function fbObjToObj(fbObj) {
const ret = {};
for (const propName of Object.keys(fbObj)) {
const key = propName;
const prop = fbObj[key];
if (prop.valueOf) {
ret[key] = prop.valueOf();
} else if (typeof prop === 'object') {
ret[key] = fbObjToObj(prop);
}
}
return ret;
}
function testBuild(monFile, jsFile) {
const arrayTable = new ArrayTableT(
'Complex Array Test',
new ArrayStructT(
221.139008,
[-700, -600, -500, -400, -300, -200, -100, 0, 100, 200, 300, 400, 500, 600, 700],
13,
[
new NestedStructT(
[233, -123],
TestEnum.B,
[TestEnum.A, TestEnum.C],
[
new OuterStructT(
false,
123.456,
new InnerStructT(
123456792.0,
[13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
91,
BigInt('9007199254740999')
),
[
new InnerStructT(
-987654321.9876,
[255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243],
123,
BigInt('9007199254741000')
),
new InnerStructT(
123000987.9876,
[101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113],
-123,
BigInt('9007199254741000')
),
],
new InnerStructT(
987654321.9876,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
19,
BigInt('9007199254741000')
),
[111000111.222, 222000222.111, 333000333.333, 444000444.444]
),
]
),
],
-123456789
)
);
const builder = new flatbuffers.Builder();
builder.finish(arrayTable.pack(builder));
if (jsFile) {
const obj = fbObjToObj(arrayTable);
writeFileSync(jsFile, `export default ${JSON.stringify(obj, null, 2)}`);
}
if (monFile) {
writeFileSync(monFile, builder.asUint8Array());
}
return builder.asUint8Array();
}
function testParse(monFile, jsFile, buffer) {
if (!buffer) {
if (!monFile) {
console.log(`Please specify mon file read the buffer from.`);
process.exit(1);
}
buffer = readFileSync(monFile);
}
const byteBuffer = new flatbuffers.ByteBuffer(new Uint8Array(buffer));
const arrayTable = ArrayTable.getRootAsArrayTable(byteBuffer).unpack();
const json = JSON.stringify(arrayTable, null, 2);
if (jsFile) {
writeFileSync(jsFile, `export default ${json}`);
}
return arrayTable;
}
if (process.argv[2] === 'build') {
testBuild(process.argv[3], process.argv[4]);
} else if (process.argv[2] === 'parse') {
testParse(process.argv[3], process.argv[4], null);
} else {
const arr = testBuild(null, null);
const parsed = testParse(null, null, Buffer.from(arr));
assert.strictEqual(parsed.a, 'Complex Array Test', 'String Test');
assert.strictEqual(parsed?.cUnderscore?.aUnderscore, 221.13900756835938, 'Float Test');
assert.deepEqual(parsed?.cUnderscore?.bUnderscore, [-700, -600, -500, -400, -300, -200, -100, 0, 100, 200, 300, 400, 500, 600, 700], 'Array of signed integers');
assert.strictEqual(parsed?.cUnderscore.d?.[0].dOuter[0].d[1].a, 123000987.9876, 'Float in deep');
assert.deepEqual(parsed?.cUnderscore?.d[0].dOuter?.[0]?.e, {
a: 987654321.9876,
b: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
c: 19,
dUnderscore: '9007199254741000',
}, 'Object in deep');
assert.deepEqual(parsed?.cUnderscore.g, ['0', '0'], 'Last object');

console.log('Arrays test: completed successfully');
}
15 changes: 14 additions & 1 deletion tests/ts/TypeScriptTest.py
Expand Up @@ -95,6 +95,18 @@ def flatc(options, schema, prefix=None, include=None, data=None, cwd=tests_path)
include="../../",
)

flatc(
options=["-b", "--schema"],
schema="arrays_test_complex/arrays_test_complex.fbs",
prefix="arrays_test_complex"
)

flatc(
options=["--ts", "--reflect-names", "--ts-flat-files", "--gen-name-strings", "--gen-object-api"],
schema="arrays_test_complex/arrays_test_complex.bfbs",
prefix="arrays_test_complex"
)

flatc(
options=[
"--ts",
Expand All @@ -121,4 +133,5 @@ def flatc(options, schema, prefix=None, include=None, data=None, cwd=tests_path)
print("Running TypeScript Tests...")
check_call(NODE_CMD + ["JavaScriptTest"])
check_call(NODE_CMD + ["JavaScriptUnionVectorTest"])
check_call(NODE_CMD + ["JavaScriptFlexBuffersTest"])
check_call(NODE_CMD + ["JavaScriptFlexBuffersTest"])
check_call(NODE_CMD + ["JavaScriptComplexArraysTest"])
Binary file not shown.
52 changes: 52 additions & 0 deletions tests/ts/arrays_test_complex/arrays_test_complex.fbs
@@ -0,0 +1,52 @@
namespace MyGame.Example;

// it appears that the library has already a problem with Enums
// when generating ts file with '--ts-flat-files' from a fbs.
// bfbs is fine.
// workaround is to generate bfbs from fbs first, and then
dbaileychess marked this conversation as resolved.
Show resolved Hide resolved
// generate flat .ts from bfbs if you have enum(s) in your chema

enum TestEnum : byte { A, B, C }

struct InnerStruct {
a:float64;
b:[ubyte:13];
c:int8;
d_underscore:int64;
}

struct OuterStruct {
a:bool;
b:double;
c_underscore:InnerStruct;
d:[InnerStruct:3];
e:InnerStruct;
f:[float64:4];
}

struct NestedStruct{
a:[int:2];
b:TestEnum;
c_underscore:[TestEnum:2];
d_outer:[OuterStruct:5];
e:[int64:2];
}

struct ArrayStruct{
a_underscore:float;
b_underscore:[int:0xF];
c:byte;
d:[NestedStruct:2];
e:int32;
f:[OuterStruct:2];
g:[int64:2];
}

table ArrayTable{
a:string;
c_underscore:ArrayStruct;
}

root_type ArrayTable;
file_identifier "RHUB";
file_extension "mon";