Kernel: Serialization does ignore actual type when trying wireTypes in unions
- Dominant language
- TypeScript
- Stars
- 2.9k
- Forks
- 267
- Avg merge
- 1d 25m
- Merged PRs (30d)
- 14
Description
### Describe the bug
When sending a value from the jsii-kernel back to the caller (<), if the type is a union the serializer just uses a fixed order to try an serialize the type. However in a union type like `CfnBucket.CorsConfigurationProperty | cdk.IResolvable`, if the actual value is an `cdk.IResolvable` (e.g. a `Lazy.Any`) the code still serializes the value as the struct type.
This is wrong, but also doesn't work because a language runtime like Python might then recurse into the struct fields and request nested values to build a struct on the language-side. Instead this should be returned as a `ReferenceType`.
### Expected Behavior
Serialize as a `ReferenceType`
### Current Behavior
Serialized as a `StructType`
### Reproduction Steps
Not quite sure, but the easiest seems to be if the jsii needs to return a `Lazy.Any` (<) that is typed as something like `CfnBucket.CorsConfigurationProperty | cdk.IResolvable`
### Possible Solution
This fixes the issue on my end:
```ts
export function process(
host: SerializerHost,
serde: keyof Serializer,
value: unknown,
type: OptionalValueOrVoid,
context: string,
) {
const wireTypes = serializationType(type, host.lookupType).filter(
({ serializationClass }) => {
if (
serde === 'serialize' &&
serializationClass === SerializationClass.Struct
) {
return (value as any)?.constructor.name !== 'LazyAny';
// return !isByReferenceOnly(value);
}
return true;
},
);
```
Unfortunately just always using `return !isByReferenceOnly(value);` causes more problems and for obvious reasons checking the constructor name is not a good idea. I suspect this check needs to be more clever in the way filters the proposed wireType in relation to the actual value.
### SDK version used
1.99.0
### Environment details (OS name and version, etc.)
any
Contributor guide
Research direction
Start at process(), especially its serializationType() wireTypes filtering and the SerializationClass.Struct branch. Trace how Lazy.Any values in unions are classified, then verify that an actual reference-like value is serialized as ReferenceType rather than StructType; the issue provides no specific file or regression test to run.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100