diff --git a/packages/@ember/-internals/deprecations/index.ts b/packages/@ember/-internals/deprecations/index.ts index b8a83a7054d..7c18ab9cda3 100644 --- a/packages/@ember/-internals/deprecations/index.ts +++ b/packages/@ember/-internals/deprecations/index.ts @@ -168,6 +168,13 @@ export const DEPRECATIONS = { until: '8.0.0', url: 'https://deprecations.emberjs.com/id/deprecate-ember-utils', }), + DEPRECATE_COMPUTED_MACROS: deprecation({ + id: 'deprecate-computed-macros', + for: 'ember-source', + since: { available: '7.5.0' }, + until: '9.0.0', + url: 'https://deprecations.emberjs.com/id/deprecate-computed-macros', + }), }; export function deprecateUntil(message: string, deprecation: DeprecationObject) { diff --git a/packages/@ember/-internals/glimmer/lib/components/link-to.ts b/packages/@ember/-internals/glimmer/lib/components/link-to.ts index d47ddd8b7ea..7bb8258f46e 100644 --- a/packages/@ember/-internals/glimmer/lib/components/link-to.ts +++ b/packages/@ember/-internals/glimmer/lib/components/link-to.ts @@ -328,7 +328,7 @@ class _LinkTo extends InternalComponent { // consume the current router state so we invalidate when QP changes // TODO: can we narrow this down to QP changes only? - consumeTag(tagFor(routing, 'currentState')); + consumeTag(tagFor(routing.router, 'currentState')); if (DEBUG) { try { @@ -417,7 +417,7 @@ class _LinkTo extends InternalComponent { // GH #17963 private currentRouteCache = createCache>(() => { - consumeTag(tagFor(this.routing, 'currentState')); + consumeTag(tagFor(this.routing.router, 'currentState')); return untrack(() => this.routing.currentRouteName); }); 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 07a2e782a3d..c74db332bf0 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 @@ -6,7 +6,10 @@ import { equalsElement, runTask, defineSimpleModifier, + expectDeprecation, + testUnless, } from 'internal-test-helpers'; +import { DEPRECATIONS } from '@ember/-internals/deprecations'; import { tracked } from '@ember/-internals/metal'; import { alias } from '@ember/object/computed'; @@ -1571,7 +1574,12 @@ moduleFor( this.assertText('3'); } - ['@test ensure aliases are watched properly [GH#17243]']() { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test ensure aliases are watched properly [GH#17243]`]() { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let fooInstance, barInstance; let FooComponent = class extends GlimmerComponent { diff --git a/packages/@ember/-internals/glimmer/tests/integration/content-test.js b/packages/@ember/-internals/glimmer/tests/integration/content-test.js index 2825d162a18..db996125b83 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/content-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/content-test.js @@ -640,7 +640,12 @@ class DynamicContentTest extends RenderingTestCase { this.assertInvariants(); } - ['@test it can render a readOnly property of a path']() { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test it can render a readOnly property of a path`]() { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let Messenger = class extends EmberObject { @readOnly('a.b.c') message; diff --git a/packages/@ember/-internals/runtime/tests/system/array_proxy/length_test.js b/packages/@ember/-internals/runtime/tests/system/array_proxy/length_test.js index 13408d36ee7..80b642e21d9 100644 --- a/packages/@ember/-internals/runtime/tests/system/array_proxy/length_test.js +++ b/packages/@ember/-internals/runtime/tests/system/array_proxy/length_test.js @@ -1,6 +1,6 @@ import ArrayProxy from '@ember/array/proxy'; -import EmberObject, { observer } from '@ember/object'; -import { oneWay as reads, not } from '@ember/object/computed'; +import EmberObject, { computed, observer } from '@ember/object'; +import { oneWay as reads } from '@ember/object/computed'; import { A as a } from '@ember/array'; import { moduleFor, @@ -39,8 +39,10 @@ moduleFor( assert ) { let proxy = class extends ArrayProxy { - @not('length') - isEmpty; + @computed('length') + get isEmpty() { + return !this.length; + } }.create({ content: a([1, 2, 3]), }); @@ -186,6 +188,11 @@ moduleFor( async [`${testUnless(DEPRECATIONS.DEPRECATE_ARRAY_PROXY.isRemoved)} @test array proxy + aliasedProperty complex test`]( assert ) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let aCalled, bCalled, cCalled, dCalled, eCalled; aCalled = bCalled = cCalled = dCalled = eCalled = 0; diff --git a/packages/@ember/object/computed.ts b/packages/@ember/object/computed.ts index 5e4d41bc33b..a00e2f120a3 100644 --- a/packages/@ember/object/computed.ts +++ b/packages/@ember/object/computed.ts @@ -1,6 +1,21 @@ export { ComputedProperty as default } from '@ember/-internals/metal/lib/computed'; export { default as expandProperties } from '@ember/-internals/metal/lib/expand_properties'; -export { default as alias } from '@ember/-internals/metal/lib/alias'; + +import { assert } from '@ember/debug'; +import internalAlias, { type AliasDecorator } from '@ember/-internals/metal/lib/alias'; +import { isDecoratorCall } from '@ember/-internals/metal/lib/decorator'; +import { deprecateComputedMacro } from './lib/computed/computed_macros'; + +export function alias(altKey: string): AliasDecorator { + assert( + 'You attempted to use @alias as a decorator directly, but it requires a `altKey` parameter', + !isDecoratorCall(Array.prototype.slice.call(arguments)) + ); + + deprecateComputedMacro('alias'); + + return internalAlias(altKey); +} export { empty, diff --git a/packages/@ember/object/lib/computed/computed_macros.ts b/packages/@ember/object/lib/computed/computed_macros.ts index 9d7a2f8d7c3..7638de8c5a0 100644 --- a/packages/@ember/object/lib/computed/computed_macros.ts +++ b/packages/@ember/object/lib/computed/computed_macros.ts @@ -15,6 +15,13 @@ import { DEPRECATIONS, deprecateUntil } from '@ember/-internals/deprecations'; @module @ember/object */ +export function deprecateComputedMacro(name: string) { + deprecateUntil( + `\`${name}\` from \`@ember/object/computed\` is deprecated. Use a getter instead.`, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS + ); +} + function expandPropertiesToArray(predicateName: string, properties: string[]) { let expandedProperties: string[] = []; @@ -43,6 +50,8 @@ function generateComputedWithPredicate(name: string, predicate: (value: unknown) !isDecoratorCall(properties) ); + deprecateComputedMacro(name); + let dependentKeys = expandPropertiesToArray(name, properties); let computedFunc = computed(...dependentKeys, function () { @@ -250,6 +259,7 @@ export function none(dependentKey: string) { @return {ComputedProperty} computed property which returns inverse of the original value for property @public + @deprecated Use a getter instead. */ export function not(dependentKey: string) { assert( @@ -257,6 +267,8 @@ export function not(dependentKey: string) { !isDecoratorCall(Array.prototype.slice.call(arguments)) ); + deprecateComputedMacro('not'); + return computed(dependentKey, function () { return !get(this, dependentKey); }); @@ -298,6 +310,7 @@ export function not(dependentKey: string) { @return {ComputedProperty} computed property which converts to boolean the original value for property @public + @deprecated Use a getter instead. */ export function bool(dependentKey: string) { assert( @@ -305,6 +318,8 @@ export function bool(dependentKey: string) { !isDecoratorCall(Array.prototype.slice.call(arguments)) ); + deprecateComputedMacro('bool'); + return computed(dependentKey, function () { return Boolean(get(this, dependentKey)); }); @@ -344,6 +359,7 @@ export function bool(dependentKey: string) { @return {ComputedProperty} computed property which match the original value for property against a given RegExp @public + @deprecated Use a getter instead. */ export function match(dependentKey: string, regexp: RegExp) { assert( @@ -351,6 +367,8 @@ export function match(dependentKey: string, regexp: RegExp) { !isDecoratorCall(Array.prototype.slice.call(arguments)) ); + deprecateComputedMacro('match'); + return computed(dependentKey, function () { let value = get(this, dependentKey); return regexp.test(value); @@ -390,6 +408,7 @@ export function match(dependentKey: string, regexp: RegExp) { @return {ComputedProperty} computed property which returns true if the original value for property is equal to the given value. @public + @deprecated Use a getter instead. */ export function equal(dependentKey: string, value: unknown) { assert( @@ -397,6 +416,8 @@ export function equal(dependentKey: string, value: unknown) { !isDecoratorCall(Array.prototype.slice.call(arguments)) ); + deprecateComputedMacro('equal'); + return computed(dependentKey, function () { return get(this, dependentKey) === value; }); @@ -435,6 +456,7 @@ export function equal(dependentKey: string, value: unknown) { @return {ComputedProperty} computed property which returns true if the original value for property is greater than given value. @public + @deprecated Use a getter instead. */ export function gt(dependentKey: string, value: number) { assert( @@ -442,6 +464,8 @@ export function gt(dependentKey: string, value: number) { !isDecoratorCall(Array.prototype.slice.call(arguments)) ); + deprecateComputedMacro('gt'); + return computed(dependentKey, function () { return get(this, dependentKey) > value; }); @@ -480,6 +504,7 @@ export function gt(dependentKey: string, value: number) { @return {ComputedProperty} computed property which returns true if the original value for property is greater or equal then given value. @public + @deprecated Use a getter instead. */ export function gte(dependentKey: string, value: number) { assert( @@ -487,6 +512,8 @@ export function gte(dependentKey: string, value: number) { !isDecoratorCall(Array.prototype.slice.call(arguments)) ); + deprecateComputedMacro('gte'); + return computed(dependentKey, function () { return get(this, dependentKey) >= value; }); @@ -525,6 +552,7 @@ export function gte(dependentKey: string, value: number) { @return {ComputedProperty} computed property which returns true if the original value for property is less then given value. @public + @deprecated Use a getter instead. */ export function lt(dependentKey: string, value: number) { assert( @@ -532,6 +560,8 @@ export function lt(dependentKey: string, value: number) { !isDecoratorCall(Array.prototype.slice.call(arguments)) ); + deprecateComputedMacro('lt'); + return computed(dependentKey, function () { return get(this, dependentKey) < value; }); @@ -570,6 +600,7 @@ export function lt(dependentKey: string, value: number) { @return {ComputedProperty} computed property which returns true if the original value for property is less or equal than given value. @public + @deprecated Use a getter instead. */ export function lte(dependentKey: string, value: number) { assert( @@ -577,6 +608,8 @@ export function lte(dependentKey: string, value: number) { !isDecoratorCall(Array.prototype.slice.call(arguments)) ); + deprecateComputedMacro('lte'); + return computed(dependentKey, function () { return get(this, dependentKey) <= value; }); @@ -625,6 +658,7 @@ export function lte(dependentKey: string, value: number) { @return {ComputedProperty} computed property which performs a logical `and` on the values of all the original values for properties. @public + @deprecated Use a getter instead. */ export const and = generateComputedWithPredicate('and', (value) => value); @@ -668,6 +702,7 @@ export const and = generateComputedWithPredicate('and', (value) => value); @return {ComputedProperty} computed property which performs a logical `or` on the values of all the original values for properties. @public + @deprecated Use a getter instead. */ export const or = generateComputedWithPredicate('or', (value) => !value); @@ -704,6 +739,7 @@ export const or = generateComputedWithPredicate('or', (value) => !value); @return {ComputedProperty} computed property which creates an alias to the original value for property. @public + @deprecated Use a getter instead. */ /** @@ -744,6 +780,7 @@ export const or = generateComputedWithPredicate('or', (value) => !value); @return {ComputedProperty} computed property which creates a one way computed property to the original value for property. @public + @deprecated Use a getter instead. */ export function oneWay(dependentKey: string) { assert( @@ -751,6 +788,8 @@ export function oneWay(dependentKey: string) { !isDecoratorCall(Array.prototype.slice.call(arguments)) ); + deprecateComputedMacro('oneWay'); + return alias(dependentKey).oneWay() as FieldDecorator; } @@ -808,6 +847,7 @@ export function oneWay(dependentKey: string) { property to the original value for property. @since 1.5.0 @public + @deprecated Use a getter instead. */ export function readOnly(dependentKey: string) { assert( @@ -815,6 +855,8 @@ export function readOnly(dependentKey: string) { !isDecoratorCall(Array.prototype.slice.call(arguments)) ); + deprecateComputedMacro('readOnly'); + return alias(dependentKey).readOnly() as FieldDecorator; } @@ -852,6 +894,7 @@ export function readOnly(dependentKey: string) { deprecation to the original value for property. @since 1.7.0 @public + @deprecated Use a getter instead. */ export function deprecatingAlias(dependentKey: string, options: DeprecationOptions) { assert( @@ -859,6 +902,8 @@ export function deprecatingAlias(dependentKey: string, options: DeprecationOptio !isDecoratorCall(Array.prototype.slice.call(arguments)) ); + deprecateComputedMacro('deprecatingAlias'); + return computed(dependentKey, { get(key) { deprecate( diff --git a/packages/@ember/object/tests/computed/computed_macros_test.js b/packages/@ember/object/tests/computed/computed_macros_test.js index c127c6aa945..ba51b84fa99 100644 --- a/packages/@ember/object/tests/computed/computed_macros_test.js +++ b/packages/@ember/object/tests/computed/computed_macros_test.js @@ -75,7 +75,12 @@ moduleFor( assert.equal(get(obj, 'LannistersKnown'), true, 'empty respects array mutations'); } - ['@test not'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test not`](assert) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { foo: true }; defineProperty(obj, 'notFoo', not('foo')); assert.equal(get(obj, 'notFoo'), false); @@ -105,7 +110,12 @@ moduleFor( assert.equal(get(obj, 'quzEmpty'), false); } - ['@test bool'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test bool`](assert) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { foo() {}, bar: 'asdf', baz: null, quz: false }; defineProperty(obj, 'fooBool', bool('foo')); defineProperty(obj, 'barBool', bool('bar')); @@ -117,7 +127,12 @@ moduleFor( assert.equal(get(obj, 'quzBool'), false); } - ['@test alias'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test alias`](assert) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { bar: 'asdf', baz: null, quz: false }; defineProperty( obj, @@ -150,7 +165,12 @@ moduleFor( assert.equal(get(obj, 'quz'), null); } - ['@test alias set'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test alias set`](assert) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = {}; let constantValue = 'always `a`'; @@ -177,7 +197,12 @@ moduleFor( assert.equal(get(obj, 'aliased'), constantValue); } - ['@test match'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test match`](assert) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { name: 'Paul' }; defineProperty(obj, 'isPaul', match('name', /Paul/)); @@ -220,7 +245,12 @@ moduleFor( assert.true(get(obj, 'isHungry'), 'undefined is none'); } - ['@test equal'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test equal`](assert) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { name: 'Paul' }; defineProperty(obj, 'isPaul', computedEqual('name', 'Paul')); @@ -231,7 +261,12 @@ moduleFor( assert.equal(get(obj, 'isPaul'), false, 'is not Paul anymore'); } - ['@test gt'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test gt`](assert) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { number: 2 }; defineProperty(obj, 'isGreaterThenOne', gt('number', 1)); @@ -246,7 +281,12 @@ moduleFor( assert.equal(get(obj, 'isGreaterThenOne'), false, 'is not gt'); } - ['@test gte'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test gte`](assert) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { number: 2 }; defineProperty(obj, 'isGreaterOrEqualThenOne', gte('number', 1)); @@ -261,7 +301,12 @@ moduleFor( assert.equal(get(obj, 'isGreaterOrEqualThenOne'), false, 'is not gte'); } - ['@test lt'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test lt`](assert) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { number: 0 }; defineProperty(obj, 'isLesserThenOne', lt('number', 1)); @@ -276,7 +321,12 @@ moduleFor( assert.equal(get(obj, 'isLesserThenOne'), false, 'is not lt'); } - ['@test lte'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test lte`](assert) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { number: 0 }; defineProperty(obj, 'isLesserOrEqualThenOne', lte('number', 1)); @@ -291,7 +341,14 @@ moduleFor( assert.equal(get(obj, 'isLesserOrEqualThenOne'), false, 'is not lte'); } - ['@test and, with two properties'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test and, with two properties`]( + assert + ) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { one: true, two: true }; defineProperty(obj, 'oneAndTwo', and('one', 'two')); @@ -312,7 +369,14 @@ moduleFor( assert.equal(get(obj, 'oneAndTwo'), 2, 'returns truthy value as in &&'); } - ['@test and, with three properties'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test and, with three properties`]( + assert + ) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { one: true, two: true, three: true }; defineProperty(obj, 'oneTwoThree', and('one', 'two', 'three')); @@ -329,7 +393,14 @@ moduleFor( assert.equal(get(obj, 'oneTwoThree'), 3, 'returns truthy value as in &&'); } - ['@test and, with expand properties'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test and, with expand properties`]( + assert + ) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { one: true, two: true, three: true }; defineProperty(obj, 'oneTwoThree', and('{one,two,three}')); @@ -346,7 +417,14 @@ moduleFor( assert.equal(get(obj, 'oneTwoThree'), 3, 'returns truthy value as in &&'); } - ['@test or, with two properties'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test or, with two properties`]( + assert + ) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { one: true, two: true }; defineProperty(obj, 'oneOrTwo', or('one', 'two')); @@ -373,7 +451,14 @@ moduleFor( assert.equal(get(obj, 'oneOrTwo'), 1, 'returns truthy value as in ||'); } - ['@test or, with three properties'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test or, with three properties`]( + assert + ) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { one: true, two: true, three: true }; defineProperty(obj, 'oneTwoThree', or('one', 'two', 'three')); @@ -404,7 +489,14 @@ moduleFor( assert.equal(get(obj, 'oneTwoThree'), 1, 'returns truthy value as in ||'); } - ['@test or, with expand properties'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test or, with expand properties`]( + assert + ) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { one: true, two: true, three: true }; defineProperty(obj, 'oneTwoThree', or('{one,two,three}')); @@ -435,7 +527,12 @@ moduleFor( assert.equal(get(obj, 'oneTwoThree'), 1, 'returns truthy value as in ||'); } - ['@test or and and, warn about dependent keys with spaces']() { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test or and and, warn about dependent keys with spaces`]() { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { one: true, two: true }; expectAssertion(function () { defineProperty(obj, 'oneOrTwo', or('one', 'two three')); @@ -446,7 +543,12 @@ moduleFor( }, /Dependent keys passed to `and` computed macro can't have spaces\./); } - ['@test oneWay'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test oneWay`](assert) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { firstName: 'Teddy', lastName: 'Zeenny', @@ -470,7 +572,12 @@ moduleFor( assert.equal(get(obj, 'nickName'), 'TeddyBear'); } - ['@test readOnly'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test readOnly`](assert) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { firstName: 'Teddy', lastName: 'Zeenny', @@ -496,7 +603,14 @@ moduleFor( assert.equal(get(obj, 'nickName'), 'TEDDDDDDDDYYY'); } - ['@test deprecatingAlias'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test deprecatingAlias`]( + assert + ) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let obj = { bar: 'asdf', baz: null, quz: false }; defineProperty( obj, diff --git a/packages/@ember/object/tests/computed_test.js b/packages/@ember/object/tests/computed_test.js index 59d294d421f..7274897300f 100644 --- a/packages/@ember/object/tests/computed_test.js +++ b/packages/@ember/object/tests/computed_test.js @@ -2,7 +2,8 @@ import { notifyPropertyChange } from '@ember/-internals/metal'; import { alias, oneWay as reads } from '@ember/object/computed'; import { A as emberA, isArray } from '@ember/array'; import EmberObject, { defineProperty, get, set, computed, observer } from '@ember/object'; -import { moduleFor, AbstractTestCase } from 'internal-test-helpers'; +import { moduleFor, AbstractTestCase, expectDeprecation, testUnless } from 'internal-test-helpers'; +import { DEPRECATIONS } from '@ember/-internals/deprecations'; function K() { return this; @@ -201,7 +202,14 @@ moduleFor( ); } - ['@test can iterate over a list of computed properties for a class'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test can iterate over a list of computed properties for a class`]( + assert + ) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let MyClass = EmberObject.extend({ foo: computed(function () {}), @@ -353,9 +361,14 @@ moduleFor( assert.strictEqual(macroCalls, 1, "the macro's getter is used"); } - ['@test observing prop installed with computed macro reads and overriding it in create() works']( + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test observing prop installed with computed macro reads and overriding it in create() works`]( assert ) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let Obj = EmberObject.extend({ name: reads('model.name'), nameDidChange: observer('name', function () {}), @@ -511,7 +524,14 @@ moduleFor( assert.deepEqual(n.normalized, ['bar']); } - ['@test lazy computation cannot cause infinite cycles'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test lazy computation cannot cause infinite cycles`]( + assert + ) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + // This is based off a real world bug found in ember-cp-validations: // https://github.com/offirgolan/ember-cp-validations/issues/659 let CycleObject = class extends EmberObject { diff --git a/packages/@ember/object/tests/create_test.js b/packages/@ember/object/tests/create_test.js index 266ac20072b..1da8049f676 100644 --- a/packages/@ember/object/tests/create_test.js +++ b/packages/@ember/object/tests/create_test.js @@ -112,8 +112,15 @@ moduleFor( } } - ['@test sets up mandatory setters for simple properties watched with aliases'](assert) { + [`${testUnless(DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isRemoved)} @test sets up mandatory setters for simple properties watched with aliases`]( + assert + ) { if (DEBUG) { + expectDeprecation( + /from `@ember\/object\/computed` is deprecated/, + DEPRECATIONS.DEPRECATE_COMPUTED_MACROS.isEnabled + ); + let MyClass = class extends EmberObject { foo = null; bar = null; diff --git a/packages/@ember/routing/lib/routing-service.ts b/packages/@ember/routing/lib/routing-service.ts index b44e2daf70c..44424525a11 100644 --- a/packages/@ember/routing/lib/routing-service.ts +++ b/packages/@ember/routing/lib/routing-service.ts @@ -4,7 +4,6 @@ import { getOwner } from '@ember/-internals/owner'; import { assert } from '@ember/debug'; -import { readOnly } from '@ember/object/computed'; import Service from '@ember/service'; import type Route from '@ember/routing/route'; import type { ModelFor } from '@ember/routing/route'; @@ -23,13 +22,24 @@ import { ROUTER } from '@ember/routing/router-service'; @class RoutingService */ export default class RoutingService extends Service { - declare targetState: EmberRouter['targetState']; - declare currentState: EmberRouter['currentState']; - declare currentRouteName: EmberRouter['currentRouteName']; - declare currentPath: EmberRouter['currentPath']; - [ROUTER]?: EmberRouter; + get targetState(): EmberRouter['targetState'] { + return this.router.targetState; + } + + get currentState(): EmberRouter['currentState'] { + return this.router.currentState; + } + + get currentRouteName(): EmberRouter['currentRouteName'] { + return this.router.currentRouteName; + } + + get currentPath(): EmberRouter['currentPath'] { + return this.router.currentPath; + } + get router(): EmberRouter { let router = this[ROUTER]; if (router !== undefined) { @@ -128,13 +138,6 @@ export default class RoutingService extends Service { } } -RoutingService.reopen({ - targetState: readOnly('router.targetState'), - currentState: readOnly('router.currentState'), - currentRouteName: readOnly('router.currentRouteName'), - currentPath: readOnly('router.currentPath'), -}); - function numberOfContextsAcceptedByHandler(handlerName: string, handlerInfos: any[]) { let req = 0; for (let i = 0; i < handlerInfos.length; i++) { diff --git a/packages/@ember/routing/router-service.ts b/packages/@ember/routing/router-service.ts index 0e4b6cae977..17f4d29e480 100644 --- a/packages/@ember/routing/router-service.ts +++ b/packages/@ember/routing/router-service.ts @@ -3,7 +3,7 @@ */ import { getOwner } from '@ember/-internals/owner'; import { assert } from '@ember/debug'; -import { readOnly } from '@ember/object/computed'; +import { dependentKeyCompat } from '@ember/object/compat'; import Service from '@ember/service'; import { consumeTag } from '@glimmer/validator/lib/tracking'; import { tagFor } from '@glimmer/validator/lib/meta'; @@ -726,8 +726,10 @@ class RouterService extends Service { @type {String | null} @public */ - @readOnly('_router.currentRouteName') - readonly currentRouteName!: this['_router']['currentRouteName']; + @dependentKeyCompat + get currentRouteName(): this['_router']['currentRouteName'] { + return this._router.currentRouteName; + } /** Current URL for the application. @@ -755,8 +757,10 @@ class RouterService extends Service { @type String @public */ - @readOnly('_router.currentURL') - readonly currentURL!: this['_router']['currentURL']; + @dependentKeyCompat + get currentURL(): this['_router']['currentURL'] { + return this._router.currentURL; + } /** The `location` property returns what implementation of the `location` API @@ -794,8 +798,10 @@ class RouterService extends Service { @see {Location} @public */ - @readOnly('_router.location') - readonly location!: this['_router']['location']; + @dependentKeyCompat + get location(): this['_router']['location'] { + return this._router.location; + } /** The `rootURL` property represents the URL of the root of @@ -824,8 +830,10 @@ class RouterService extends Service { @default '/' @public */ - @readOnly('_router.rootURL') - readonly rootURL!: this['_router']['rootURL']; + @dependentKeyCompat + get rootURL(): this['_router']['rootURL'] { + return this._router.rootURL; + } /** The `currentRoute` property contains metadata about the current leaf route. @@ -856,8 +864,10 @@ class RouterService extends Service { @type RouteInfo @public */ - @readOnly('_router.currentRoute') - readonly currentRoute!: this['_router']['currentRoute']; + @dependentKeyCompat + get currentRoute(): this['_router']['currentRoute'] { + return this._router.currentRoute; + } } export { RouterService as default, type RouteInfo, type RouteInfoWithAttributes }; diff --git a/packages/ember/tests/routing/router_service_test/currenturl_lifecycle_test.js b/packages/ember/tests/routing/router_service_test/currenturl_lifecycle_test.js index 05f80311eb4..71c55426b1e 100644 --- a/packages/ember/tests/routing/router_service_test/currenturl_lifecycle_test.js +++ b/packages/ember/tests/routing/router_service_test/currenturl_lifecycle_test.js @@ -1,6 +1,5 @@ import { service } from '@ember/service'; -import { action } from '@ember/object'; -import { readOnly } from '@ember/object/computed'; +import { action, computed } from '@ember/object'; import Component from '@glimmer/component'; import Route from '@ember/routing/route'; import { get } from '@ember/object'; @@ -131,12 +130,18 @@ moduleFor( let CurrenURLComponent = class extends Component { @service('router') routerService; - @readOnly('routerService.currentURL') - currentURL; - @readOnly('routerService.currentRouteName') - currentRouteName; - @readOnly('routerService.currentRoute') - currentRoute; + + get currentURL() { + return this.routerService.currentURL; + } + + get currentRouteName() { + return this.routerService.currentRouteName; + } + + get currentRoute() { + return this.routerService.currentRoute; + } }; this.add( @@ -294,6 +299,29 @@ moduleFor( }); } + async ['@test a computed property can depend on RouterService#currentURL'](assert) { + await this.visit('/'); + + let routerService = this.routerService; + + class Watcher { + routerService = routerService; + + @computed('routerService.currentURL') + get currentURL() { + return this.routerService.currentURL; + } + } + + let watcher = new Watcher(); + + assert.strictEqual(watcher.currentURL, '/'); + + await this.visit('/child'); + + assert.strictEqual(watcher.currentURL, '/child'); + } + ['@test RouterService#currentURL is correctly set with component after consecutive visits']( assert ) {