Ember.js: observers on `alias`, `reads` and `readOnly` computed properties don't fire in `3.13.beta-4`

Created on 27 Aug 2019  路  6Comments  路  Source: emberjs/ember.js

There seems to be a regression in 3.13.beta-4 where observers which observe alias, reads and readOnly computed properties don't fire.

In 3.12, the four observers fire when count is mutated. In 3.13.0-beta.4, only the countObserver fires.

button.js

import Component from '@ember/component';
import { action, observer } from '@ember/object';
import { alias, readOnly, reads } from '@ember/object/computed';

export default Component.extend({
  count: 0,
  increment: action(function() {
    this.incrementProperty('count');
  }),

  countAlias: alias('count'),
  countReads: reads('count'),
  countReadOnly: readOnly('count'),

  countObserver: observer('count', function() {
    console.log('count has changed');
  }),

  countAliasObserver: observer('countAlias', function() {
    console.log('countAlias has changed..');
  }),

  countReadsObserver: observer('countReads', function() {
    console.log('countReads has changed..');
  }),

  countReadOnlyObserver: observer('countReadOnly', function() {
    console.log('countReadOnly has changed..');
  }),
});

button.hbs:

<button {{on 'click' this.increment}}>+</button>

<h2>Count: {{this.count}}</h2>

3.12.0:

3 12

3.13.0.beta-4:

3 13 0 beta-4

Bug

Most helpful comment

@GavinJoyce this bugfix part of this is actually more narrow than what was changed. The outstanding bug was that observing an alias not force a stale CP, but it also caused observing an alias to act like a stale CP even when its target CP had a current value which was not an intentional regression.

The hope is that combinations of observing, getting, and invalidating CP is the same whether you use the alias for some of those ops and the target for other ops. The alias use case was an alternate name, the original use was our transition from "content" to "model". Whereas the use case of a CP was derived state, it is expected that a user of the CP not mix both usage of the source state and derived state but only use it through the derived state, in which case the above behavior is intentional.

All 6 comments

/cc @pzuraq

@GavinJoyce - Thank you for the detailed bug report!

This is a known and expected change. Previously, observing an alias would cause that alias to _eagerly_ compute, accessing (and computing) the alias value as well. This was a difference in behavior between aliases and standard CPs, but not something that could be easily worked around with the implementation of aliases. I also believe this was the source of a number of bug reports, will see if I can find them when I have time.

In beta, aliases work like standard CPs - they do not activate or propagate changes until they have been calculated for the first time. This means that observers watching an alias will not trigger until the alias has been used at least once.

This should be possible to change back if this change would cause regressions, but we saw it as a bugfix at the time which is why we went through with it. cc @krisselden

Thanks for the explanation @pzuraq. FWIW, this has only surfaced as an issue in a couple of places in our large app and the fix of observing the original property instead of the alias is a pretty straightforward fix

@GavinJoyce this bugfix part of this is actually more narrow than what was changed. The outstanding bug was that observing an alias not force a stale CP, but it also caused observing an alias to act like a stale CP even when its target CP had a current value which was not an intentional regression.

The hope is that combinations of observing, getting, and invalidating CP is the same whether you use the alias for some of those ops and the target for other ops. The alias use case was an alternate name, the original use was our transition from "content" to "model". Whereas the use case of a CP was derived state, it is expected that a user of the CP not mix both usage of the source state and derived state but only use it through the derived state, in which case the above behavior is intentional.

Was this page helpful?
0 / 5 - 0 ratings