in packages/@jsii/kernel/src/serialization.ts [659:765]
serialize(value, _type, host) {
if (value == null) {
return undefined;
}
if (isDate(value)) {
return serializeDate(value);
}
if (isScalar(value)) {
return value;
}
if (Array.isArray(value)) {
return value.map((e, idx) =>
process(
host,
'serialize',
e,
{ type: spec.CANONICAL_ANY },
`index ${inspect(idx)}`,
),
);
}
// Note: no case for "ENUM" here, without type declaration we can't tell the difference
// between an enum member and a scalar.
if (typeof value === 'function') {
throw new SerializationError(
'Functions cannot be passed across language boundaries',
value,
host,
);
}
if (typeof value !== 'object' || value == null) {
throw new SerializationError(
`A jsii kernel assumption was violated: value is not an object`,
value,
host,
);
}
if (
SYMBOL_WIRE_TYPE in value &&
(value as any)[SYMBOL_WIRE_TYPE] === TOKEN_MAP
) {
return SERIALIZERS[SerializationClass.Map].serialize(
value,
{
type: {
collection: {
kind: spec.CollectionKind.Map,
elementtype: spec.CANONICAL_ANY,
},
},
},
host,
);
}
// To make sure people aren't going to try and return Map<> or Set<> out, test for
// those and throw a descriptive error message. We can't detect these cases any other
// way, and the by-value serialized object will be quite useless.
if (value instanceof Set || value instanceof Map) {
throw new SerializationError(
'Set and Map instances cannot be sent across the language boundary',
value,
host,
);
}
// Use a previous reference to maintain object identity. NOTE: this may cause us to return
// a different type than requested! This is just how it is right now.
// https://github.com/aws/jsii/issues/399
const prevRef = objectReference(value);
if (prevRef) {
return prevRef;
}
// If this is or should be a reference type, pass or make the reference
// (Like regular reftype serialization, but without the type derivation to an interface)
const jsiiType =
jsiiTypeFqn(value, host.isVisibleType) ??
(isByReferenceOnly(value) ? EMPTY_OBJECT_FQN : undefined);
if (jsiiType) {
return host.objects.registerObject(value, jsiiType);
}
// At this point we have an object that is not of an exported type. Either an object
// literal, or an instance of a fully private class (cannot distinguish those cases).
// We will serialize by-value, but recurse for serialization so that if
// the object contains reference objects, they will be serialized appropriately.
// (Basically, serialize anything else as a map of 'any').
return mapValues(
value,
(v, key) =>
process(
host,
'serialize',
v,
{ type: spec.CANONICAL_ANY },
`key ${inspect(key)}`,
),
host,
);
},