fix(javascript): honor declared element types for root container registration - #4013
fix(javascript): honor declared element types for root container registration#4013ayush00git wants to merge 4 commits into
Conversation
…stration Registering a root Type.list/set/map with declared element types returned the internal any-typed container serializer, silently discarding the declared generics (e.g. declared float32 elements kept float64 dynamic encoding). Generate a dedicated serializer for such registrations, bind it to the returned root deserializer, and keep it out of the type-id keyed registry so dynamic container dispatch stays untouched.
| // The type-id keyed registry only holds the dynamic container | ||
| // serializer; a container with declared element types gets a dedicated | ||
| // serializer for this registration. | ||
| return this.generate(typeInfo); |
There was a problem hiding this comment.
Registering the container before its extension codec now leaves the generated serializer bound to undefined, even when all registration finishes before the first root operation:
class E {}
Type.ext(901)(E);
const fory = new Fory({ compatible: false });
const list = fory.register(Type.list(Type.ext(901)));
fory.register(E, { write() {}, read() {} });
list.serialize([new E()]);traversalContainer() creates forward placeholders for structs but not extensions, so ExtSerializerGenerator.writeEmbed() captures the missing serializer in a factory-level constant. Registering E afterward cannot update that constant, and serialization fails at ext_ser.writeTypeInfo(null). Sets have the same issue. The previous dynamic root serializer resolved the codec at write time.
Please preserve registration ordering before the first operation by ensuring the generated container binds to the completed extension codec, and add a regression test for this order.
A declared container generated before its extension codec captured undefined, because traversalContainer only created forward placeholders for struct types. Serialization then failed at the ext serializer's writeTypeInfo. Register the same forward placeholder for ext types so the generated container binds to the placeholder object that the later codec registration fills, preserving free registration order before the first root operation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HDxaC93cfnTxCciswW1NHM
What was the error
Registering a root container with declared element types, e.g.
fory.register(Type.list(Type.float32())), silently returned the internal any-typed container serializer. The declared generics were discarded: elements were written with dynamic dispatch instead of the declared type, so declaredfloat32/int64semantics were lost at the root while the same declaration worked as a struct field.What this PR fixes
A root
Type.list/Type.set/Type.mapwith declared element types now gets a dedicated generated serializer, bound to the returned root serialize/deserialize pair. It is kept out of the type-id keyed registry so dynamic container dispatch stays untouched. Regression tests cover root list, set, and map plus the dynamic-dispatch guard.