Search before asking
Version
- Apache Fory:
83522b197 (reproduced locally)
- OS: macOS
- Node.js: v20.20.2
Component(s)
JavaScript
Minimal reproduce step
From a checkout of 83522b197:
cd javascript
npm install
npm run build
node - <<'NODE'
const { default: Fory, Type } = require("./packages/core/dist");
const { BinaryReader } = require("./packages/core/dist/lib/reader");
const { TypeId } = require("./packages/core/dist/lib/type");
const fory = new Fory({ compatible: false, ref: false });
const registration = fory.register(
Type.list(Type.int32({ encoding: "fixed" })),
);
const bytes = registration.serialize([1, 2, 3]);
const reader = new BinaryReader({});
reader.reset(bytes);
reader.readUint8(); // root bitmap
reader.readInt8(); // root flag
reader.readUint8(); // root type id for LIST
reader.readVarUint32Small7(); // list length
reader.readUint8(); // list header (= 8, same type but not declared type)
console.log({
int32_type_id: TypeId.INT32,
varint32_type_id: TypeId.VARINT32,
});
console.log({
desired_type_id: TypeId.INT32,
actual_type_id: reader.readUint8(), // element type info
});
NODE
What did you expect to see?
The registered root schema explicitly declares int32 with encoding: "fixed". I expected the serializer to use that registered type to serialize its elements instead of inferring the type.
For this example, the list header should remain 0x08 (same type, without a declared element type), followed by TypeId.INT32 (4) as inline type information. A root collection has no enclosing schema, so the output must remain self-describing.
What did you see instead?
The output is:
{ int32_type_id: 4, varint32_type_id: 5 }
{ desired_type_id: 4, actual_type_id: 5 }
The element type ID is not consistent with the fixed int32 schema. Fory infers the element type from the JavaScript runtime values instead, so integer number values use VARINT32 (5) rather than the registered INT32 (4) (see [1]).
The same declared schema is honored when the collection is a field of a registered struct, for example
Type.struct("User", { scores: Type.list(Type.int32({ encoding: "fixed" })) });
The inconsistency only occurs when the typed collection itself is registered and serialized as the root value.
The same behavior also affects Type.set(...) and Type.map(...) collections.
Anything Else?
This is a correctness issue first. The fix should also improve typed root collection serialization performance by avoiding runtime type inference and dynamic serializer selection.
[1] The registered generic schema reaches the raw list<any> serializer: Gen.generateSerializer retrieves an existing serializer by container type ID. The dynamic writer then calls getSerializerByData(item), which maps ordinary integer JavaScript number values to VARINT32, without consulting the registered generic schema.
Are you willing to submit a PR?
Search before asking
Version
83522b197(reproduced locally)Component(s)
JavaScript
Minimal reproduce step
From a checkout of
83522b197:What did you expect to see?
The registered root schema explicitly declares
int32withencoding: "fixed". I expected the serializer to use that registered type to serialize its elements instead of inferring the type.For this example, the list header should remain
0x08(same type, without a declared element type), followed byTypeId.INT32(4) as inline type information. A root collection has no enclosing schema, so the output must remain self-describing.What did you see instead?
The output is:
The element type ID is not consistent with the fixed
int32schema. Fory infers the element type from the JavaScript runtime values instead, so integernumbervalues useVARINT32(5) rather than the registeredINT32(4) (see [1]).The same declared schema is honored when the collection is a field of a registered struct, for example
The inconsistency only occurs when the typed collection itself is registered and serialized as the root value.
The same behavior also affects
Type.set(...)andType.map(...)collections.Anything Else?
This is a correctness issue first. The fix should also improve typed root collection serialization performance by avoiding runtime type inference and dynamic serializer selection.
[1] The registered generic schema reaches the raw
list<any>serializer:Gen.generateSerializerretrieves an existing serializer by container type ID. The dynamic writer then callsgetSerializerByData(item), which maps ordinary integer JavaScriptnumbervalues toVARINT32, without consulting the registered generic schema.Are you willing to submit a PR?