BrianLii opened a new issue, #4009: URL: https://github.com/apache/fory/issues/4009
### Search before asking - [x] I had searched in the [issues](https://github.com/apache/fory/issues) and found no similar issues. ### Version - Apache Fory: `83522b197` (reproduced locally) - OS: macOS - Node.js: v20.20.2 ### Component(s) JavaScript ### Minimal reproduce step From a checkout of `83522b197`: ```ts 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: ```javascript { 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 ```ts 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`](https://github.com/apache/fory/blob/83522b197/javascript/packages/core/lib/gen/index.ts#L176-L182) retrieves an existing serializer by container type ID. The dynamic writer then calls [`getSerializerByData(item)`](https://github.com/apache/fory/blob/83522b197/javascript/packages/core/lib/gen/collection.ts#L182-L208), which maps ordinary integer JavaScript `number` values to [`VARINT32`](https://github.com/apache/fory/blob/83522b197/javascript/packages/core/lib/typeResolver.ts#L350-L369), without consulting the registered generic schema. ### Are you willing to submit a PR? - [x] I'm willing to submit a PR! -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
