diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/curly-components-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/curly-components-test.js index 80a864e5418..1a11155d4fc 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/curly-components-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/curly-components-test.js @@ -13,7 +13,7 @@ import { import { run } from '@ember/runloop'; import { DEBUG } from '@glimmer/env'; -import { set, get, observer, on, computed } from '@ember/-internals/metal'; +import { alias, set, get, observer, on, computed } from '@ember/-internals/metal'; import Service, { inject as injectService } from '@ember/service'; import { Object as EmberObject, A as emberA } from '@ember/-internals/runtime'; import { jQueryDisabled } from '@ember/-internals/views'; @@ -3576,6 +3576,67 @@ moduleFor( this.render('{{foo-bar}}'); } + + ['@test ensure aliases are watched properly [GH#17243]']() { + let fooInstance, barInstance; + + let FooComponent = Component.extend({ + source: 'first', + foo: alias('source'), + + init() { + this._super(...arguments); + fooInstance = this; + }, + }); + + this.registerComponent('foo', { + ComponentClass: FooComponent, + template: '{{this.foo}}', + }); + + let BarComponent = Component.extend({ + target: null, + + init() { + this._super(...arguments); + barInstance = this; + }, + + bar: computed('target.foo', function() { + if (this.target) { + return this.target.foo.toUpperCase(); + } + }), + }); + + this.registerComponent('bar', { + ComponentClass: BarComponent, + template: '{{this.bar}}', + }); + + this.render('[][]'); + + this.assertText('[first][]'); + + // addObserver + runTask(() => set(barInstance, 'target', fooInstance)); + + this.assertText('[first][FIRST]'); + + runTask(() => set(fooInstance, 'source', 'second')); + + this.assertText('[second][SECOND]'); + + // removeObserver + runTask(() => set(barInstance, 'target', null)); + + this.assertText('[second][]'); + + runTask(() => set(fooInstance, 'source', 'third')); + + this.assertText('[third][]'); + } } ); diff --git a/packages/@ember/-internals/metal/lib/alias.ts b/packages/@ember/-internals/metal/lib/alias.ts index 38471c23882..b8f3b6cdb1e 100644 --- a/packages/@ember/-internals/metal/lib/alias.ts +++ b/packages/@ember/-internals/metal/lib/alias.ts @@ -46,10 +46,6 @@ export class AliasedProperty extends Descriptor implements DescriptorWithDepende this.consume(obj, keyName, meta); } - didUnwatch(obj: object, keyName: string, meta: Meta): void { - this.unconsume(obj, keyName, meta); - } - get(obj: object, keyName: string): any { let ret = get(obj, this.altKey); this.consume(obj, keyName, metaFor(obj)); diff --git a/packages/@ember/-internals/metal/tests/alias_test.js b/packages/@ember/-internals/metal/tests/alias_test.js index 0546b99ea32..29a7defff42 100644 --- a/packages/@ember/-internals/metal/tests/alias_test.js +++ b/packages/@ember/-internals/metal/tests/alias_test.js @@ -7,6 +7,7 @@ import { addObserver, removeObserver, tagFor, + tagForProperty, } from '..'; import { meta } from '@ember/-internals/meta'; import { moduleFor, AbstractTestCase } from 'internal-test-helpers'; @@ -164,5 +165,57 @@ moduleFor( assert.equal(count, 2); } + + ['@test property tags are bumped when the source changes [GH#17243]'](assert) { + function assertPropertyTagChanged(obj, keyName, callback) { + let tag = tagForProperty(obj, keyName); + let before = tag.value(); + + callback(); + + let after = tag.value(); + + assert.notEqual(after, before, `tagForProperty ${keyName} should change`); + } + + function assertPropertyTagUnchanged(obj, keyName, callback) { + let tag = tagForProperty(obj, keyName); + let before = tag.value(); + + callback(); + + let after = tag.value(); + + assert.equal(after, before, `tagForProperty ${keyName} should not change`); + } + + defineProperty(obj, 'bar', alias('foo.faz')); + + assertPropertyTagUnchanged(obj, 'bar', () => { + assert.equal(get(obj, 'bar'), 'FOO'); + }); + + assertPropertyTagChanged(obj, 'bar', () => { + set(obj, 'foo.faz', 'BAR'); + }); + + assertPropertyTagUnchanged(obj, 'bar', () => { + assert.equal(get(obj, 'bar'), 'BAR'); + }); + + assertPropertyTagUnchanged(obj, 'bar', () => { + // trigger willWatch, then didUnwatch + addObserver(obj, 'bar', incrementCount); + removeObserver(obj, 'bar', incrementCount); + }); + + assertPropertyTagChanged(obj, 'bar', () => { + set(obj, 'foo.faz', 'FOO'); + }); + + assertPropertyTagUnchanged(obj, 'bar', () => { + assert.equal(get(obj, 'bar'), 'FOO'); + }); + } } );