formatDescriptor() throws on certain deserialized descriptors with deeply-nested self-references
ninevra opened this issue · comments
When formatDescriptor()
is called on a deserialized descriptor of an object with a self-referential property at a nesting depth beyond maxDepth
, it may throw a PointerLookupError
.
MRE:
const value = {};
const actualDescriptor = concordance.describe({
a: {
b: value
},
c: value
});
const serializedActual = concordance.serialize(actualDescriptor);
const deserializedActual = concordance.deserialize(serializedActual);
concordance.formatDescriptor(deserializedActual, {maxDepth: 1});
This throws:
PointerLookupError {
index: 3,
message: 'Could not deserialize buffer: pointer 3 could not be resolved',
}
› mapPointerDescriptor (node_modules/concordance/lib/serialize.js:321:67)
› node_modules/concordance/lib/serialize.js:336:14
› deserializeRecord (node_modules/concordance/lib/serialize.js:255:12)
› recursor (node_modules/concordance/lib/serialize.js:264:12)
› deserializeComplex (node_modules/concordance/lib/metaDescriptors/property.js:18:17)
› node_modules/concordance/lib/serialize.js:336:35
› deserializeRecord (node_modules/concordance/lib/serialize.js:267:10)
› Object.recursor [as next] (node_modules/concordance/lib/serialize.js:264:12)
› Object.next [as recursor] (node_modules/concordance/lib/recursorUtils.js:59:44)
› Object.formatDescriptor (node_modules/concordance/lib/format.js:74:35)
To reproduce the issue, the following must hold:
- The provided
maxDepth
is non-zero - The deeply-nested self-reference occurs at a depth greater than
maxDepth
- The shallow self-reference occurs at a depth at most
maxDepth
- The name of the property containing the deeply-nested self-reference is lexically less than the name of the property containing the shallow self-reference
I believe the problem to be that the descriptor is deserialized lazily, and the formatter never calls upon the deeply-nested self-referential value, so when the shallow self-reference is called upon, its pointer references a descriptor that hasn't been deserialized yet.
I first encountered this in AVA, where it can cause an error to be thrown when a snapshot assertion comparing against such a value fails.
I'm working on a PR that may fix this presently.
diffDescriptors()
is also affected; that's AVA's entry point to this.