concordancejs / concordance

Compare, format, diff and serialize any JavaScript value

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Adding iterator to binary tree structure breaks representation

jcubic opened this issue · comments

This is related to avajs/ava#2811

Here is simple reproducation:

const concordance = require('concordance');


function Pair(car, cdr) {
  this.car = car;
  this.cdr = cdr;
}

function Nil() {}
var nil = new Nil();


var x = new Pair(
    new Pair(
        new Pair(
            10,
            new Pair(
                20,
                nil
            )
        ),
        nil
    ),
    nil
);


let data = concordance.describe(x);
console.log(concordance.format(data));



Pair.prototype[Symbol.iterator] = function() {
    var node = this;
    return {
        next: function() {
            var cur = node;
            node = cur.cdr;
            if (cur === nil) {
                return { value: undefined, done: true };
            } else {
                return { value: cur.car, done: false };
            }
        }
    };
};

data = concordance.describe(x);
console.log(concordance.format(data));

Here is the output:

@Object {
  ctor: 'Pair',
  describeAny: Function describeAny {},
  describeItem: Function describeItem {},
  describeMapEntry: Function describeMapEntry {},
  describeProperty: Function describeProperty {},
  isArray: false,
  isIterable: false,
  isList: false,
  iterableState: null,
  listState: null,
  pointer: 1,
  propertyState: null,
  stringTag: 'Object',
  value: Pair {
    car: Pair {
      car: Pair {
        car: 10,
        cdr: Pair {
          car: 20,
          cdr: Nil {},
        },
      },
      cdr: Nil {},
    },
    cdr: Nil {},
  },
}
@Object {
  ctor: 'Pair',
  describeAny: Function describeAny {},
  describeItem: Function describeItem {},
  describeMapEntry: Function describeMapEntry {},
  describeProperty: Function describeProperty {},
  isArray: false,
  isIterable: true,
  isList: false,
  iterableState: null,
  listState: null,
  pointer: 1,
  propertyState: null,
  stringTag: 'Object',
  value: Pair {
    car: Pair {
      car: Pair {
        car: 10,
        cdr: Pair {
          car: 20,
          cdr: Nil {},
          ---
          20,
        },
        ---
        10,
        20,
      },
      cdr: Nil {},
      ---
      Pair {
        car: 10,
        cdr: Pair {
          car: 20,
          cdr: Nil {},
          ---
          20,
        },
        ---
        10,
        20,
      },
    },
    cdr: Nil {},
    ---
    Pair {
      car: Pair {
        car: 10,
        cdr: Pair {
          car: 20,
          cdr: Nil {},
          ---
          20,
        },
        ---
        10,
        20,
      },
      cdr: Nil {},
      ---
      Pair {
        car: 10,
        cdr: Pair {
          car: 20,
          cdr: Nil {},
          ---
          20,
        },
        ---
        10,
        20,
      },
    },
  },
}

There doesn't seem to be an error though — what am I looking for?

There are two different outputs, the second one has a lot of duplicated data in value, which is invalid tree structure. The output should be the same after adding the iterator.

The output for second print should be:

  value: Pair {
    car: Pair {
      car: Pair {
        car: 10,
        cdr: Pair {
          car: 20,
          cdr: Nil {},
        },
      },
      cdr: Nil {},
    },
    cdr: Nil {},
  },

I don't understand what those other data suppose to be, why they are duplicated?

Also what is --- in output?

Note that I only want to know if the output is correct. So I can finally be sure that my tests that use snapshots are working after adding iterator. Because the snapshot says the output is different and that tests are broken.

Gotcha, I think I tried to answer this in the original AVA issue but it got lost in the confusion around snapshots failing and then passing. Sorry for the confusion!

Concordance / AVA does iterate over objects when serializing / t.snapshot() and comparing / t.deepEqual(). The --- separates the own-properties of the object from the iterated items.

Generally this is nice, in that custom iterables may have a couple fields and yield a bunch of items. In your case it's confusing because the iteration yields the same values as are available directly on the object (I think?).

avajs/ava#1861 may be of interest, it would let you extend AVA to recognize your objects and format / compare them as appropriate.

Thanks for the explanation, yes the iteration return the same values as are in objects properties. They are linked lists and iteration just returns an array of the items in that list.

Thanks again for taking the time to think about my issue.