arqex / freezer

A tree data structure that emits events on updates, even if the modification is triggered by one of the leaves, making it easier to think in a reactive way.
MIT License
1.28k stars 56 forks source link

Set doesn't return the correct pivoted node if node contents wasn't changed #72

Closed dchest closed 7 years ago

dchest commented 8 years ago

When a pivoted node's child was not updated because it was the same, pivoting would return this child node instead of the pivoted node.

For example:

var freezer = new Freezer({
  user: {
    ui: {
      loaded: false
    },
    data: {
      name: ''
    }
  }
});

function update(name) {
  var pv = freezer.get().user.pivot()
                .ui.set('loaded', true);
  console.log(pv);
  pv.data.set('name', name);
}

update('Dmitry');
update('arqex');

This will throw "TypeError: Cannot read property 'set' of undefined at update, because the second time we call update, ui.loaded didn't change and setting it returns ui node, not user node.

See example live here: http://jsbin.com/pujeyu/edit?html,js,console,output

My guess is that here in set: https://github.com/arqex/freezer/blob/2b1a2fcc53372993c6a970a9a9d48ae3582169cd/src/mixins.js#L43-L45

instead of just returning the node:

            // No changes, just return the node
            if( !update )
                return this;

we should find pivot and return it if it exists:

            // No changes, just return the node
            if( !update ) {
                var pivot = Utils.findPivot( this );
                if( pivot ) {
                    return pivot;
                }
                return this;
            }