diff --git a/index.html b/index.html
index 77ad682afac..ba2b0bcf2fe 100644
--- a/index.html
+++ b/index.html
@@ -34,7 +34,7 @@
QUnit.config.urlConfig.push({
id: 'OVERRIDE_DEPRECATION_VERSION',
- value: ['20.0.0', '6.0.0', '5.12.0'],
+ value: ['20.0.0', '8.0.0', '7.12.0', '6.0.0', '5.12.0'],
label: 'Deprecation Version',
});
diff --git a/packages/@ember/-internals/deprecations/index.ts b/packages/@ember/-internals/deprecations/index.ts
index 9b1c7e93827..9625d864bc5 100644
--- a/packages/@ember/-internals/deprecations/index.ts
+++ b/packages/@ember/-internals/deprecations/index.ts
@@ -119,6 +119,13 @@ export const DEPRECATIONS = {
until: '7.5.0',
url: 'https://deprecations.emberjs.com/id/deprecate-comparable-mixin',
}),
+ DEPRECATE_TARGET_ACTION_SUPPORT: deprecation({
+ for: 'ember-source',
+ id: 'deprecate-target-action-support',
+ since: { available: '7.3.0' },
+ until: '8.0.0',
+ url: 'https://deprecations.emberjs.com/id/deprecate-target-action-support',
+ }),
};
export function deprecateUntil(message: string, deprecation: DeprecationObject) {
diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/target-action-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/target-action-test.js
index 84a7f2a27b0..2b6c77a479d 100644
--- a/packages/@ember/-internals/glimmer/tests/integration/components/target-action-test.js
+++ b/packages/@ember/-internals/glimmer/tests/integration/components/target-action-test.js
@@ -1,17 +1,31 @@
-import { moduleFor, RenderingTestCase, runTask } from 'internal-test-helpers';
+import {
+ expectDeprecation,
+ moduleFor,
+ RenderingTestCase,
+ runTask,
+ testUnless,
+} from 'internal-test-helpers';
import { action, set } from '@ember/object';
import Mixin from '@ember/object/mixin';
import Controller from '@ember/controller';
import EmberObject from '@ember/object';
+import { DEPRECATIONS } from '@ember/-internals/deprecations';
import { Component } from '../../utils/helpers';
moduleFor(
'Components test: send',
class extends RenderingTestCase {
- ['@test sending to undefined actions triggers an error'](assert) {
- assert.expect(2);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test sending to undefined actions triggers an error`](assert) {
+ assert.expect(3);
+
+ expectDeprecation(
+ /Calling `\.send\(\)` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
let component;
@@ -39,7 +53,14 @@ moduleFor(
}, /had no action handler for: baz/);
}
- ['@test `send` will call send from a target if it is defined']() {
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test \`send\` will call send from a target if it is defined`]() {
+ expectDeprecation(
+ /Calling `\.send\(\)` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
+
let component;
let target = {
send: (message, payload) => {
@@ -64,8 +85,15 @@ moduleFor(
runTask(() => component.send('foo', 'baz'));
}
- ['@test a handled action can be bubbled to the target for continued processing']() {
- this.assert.expect(2);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test a handled action can be bubbled to the target for continued processing`]() {
+ this.assert.expect(3);
+
+ expectDeprecation(
+ /Calling `\.send\(\)` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
let component;
@@ -97,8 +125,15 @@ moduleFor(
runTask(() => component.send('poke'));
}
- ["@test action can be handled by a superclass' actions object"](assert) {
- this.assert.expect(4);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test action can be handled by a superclass' actions object`](assert) {
+ this.assert.expect(5);
+
+ expectDeprecation(
+ /Calling `\.send\(\)` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
let component;
@@ -166,7 +201,14 @@ moduleFor(
});
}
- ['@test asserts if called on a destroyed component']() {
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test asserts if called on a destroyed component`]() {
+ expectDeprecation(
+ /Calling `\.send\(\)` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
+
let component;
this.owner.register(
diff --git a/packages/@ember/-internals/runtime/lib/mixins/action_handler.ts b/packages/@ember/-internals/runtime/lib/mixins/action_handler.ts
index bab591600ee..116d52c8c3e 100644
--- a/packages/@ember/-internals/runtime/lib/mixins/action_handler.ts
+++ b/packages/@ember/-internals/runtime/lib/mixins/action_handler.ts
@@ -5,6 +5,7 @@
import Mixin from '@ember/object/mixin';
import { get } from '@ember/-internals/metal/lib/property_get';
import { assert } from '@ember/debug';
+import { deprecateUntil, DEPRECATIONS } from '@ember/-internals/deprecations';
/**
`ActionHandler` is available on some familiar classes including
@@ -164,6 +165,7 @@ const ActionHandler = Mixin.create({
```
@property actions
+ @deprecated Use the `@action` decorator instead.
@type Object
@default null
@public
@@ -197,11 +199,16 @@ const ActionHandler = Mixin.create({
```
@method send
+ @deprecated Use direct method calls instead.
@param {String} actionName The action to trigger
@param {*} context a context to send with the action
@public
*/
send(actionName: string, ...args: any[]) {
+ deprecateUntil(
+ `Calling \`.send()\` on ${this} is deprecated. Invoke the corresponding method directly.`,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT
+ );
assert(
`Attempted to call .send() with the action '${actionName}' on the destroyed object '${this}'.`,
!this.isDestroying && !this.isDestroyed
diff --git a/packages/@ember/-internals/runtime/lib/mixins/target_action_support.ts b/packages/@ember/-internals/runtime/lib/mixins/target_action_support.ts
index 534bf7c68b8..6937ec312dd 100644
--- a/packages/@ember/-internals/runtime/lib/mixins/target_action_support.ts
+++ b/packages/@ember/-internals/runtime/lib/mixins/target_action_support.ts
@@ -7,6 +7,7 @@ import { get } from '@ember/-internals/metal/lib/property_get';
import computed from '@ember/-internals/metal/lib/computed';
import Mixin from '@ember/object/mixin';
import { assert } from '@ember/debug';
+import { deprecateUntil, DEPRECATIONS } from '@ember/-internals/deprecations';
import { DEBUG } from '@glimmer/env';
/**
@@ -104,11 +105,17 @@ const TargetActionSupport = Mixin.create({
```
@method triggerAction
+ @deprecated Use a direct method call or closure action instead.
@param opts {Object} (optional, with the optional keys action, target and/or actionContext)
@return {Boolean} true if the action was sent successfully and did not return false
@private
*/
triggerAction(opts: { action?: string; target?: unknown; actionContext?: unknown } = {}) {
+ deprecateUntil(
+ `Calling \`triggerAction\` on ${this} is deprecated. Invoke the target method directly.`,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT
+ );
+
let { action, target, actionContext } = opts;
action = action || get(this, 'action');
target = target || getTarget(this);
diff --git a/packages/@ember/-internals/runtime/tests/mixins/target_action_support_test.js b/packages/@ember/-internals/runtime/tests/mixins/target_action_support_test.js
index be9eb69ea7b..13fae5111ed 100644
--- a/packages/@ember/-internals/runtime/tests/mixins/target_action_support_test.js
+++ b/packages/@ember/-internals/runtime/tests/mixins/target_action_support_test.js
@@ -1,7 +1,8 @@
import { context } from '@ember/-internals/environment';
import EmberObject from '@ember/object';
import TargetActionSupport from '../../lib/mixins/target_action_support';
-import { moduleFor, AbstractTestCase } from 'internal-test-helpers';
+import { expectDeprecation, moduleFor, AbstractTestCase, testUnless } from 'internal-test-helpers';
+import { DEPRECATIONS } from '../../../deprecations';
let originalLookup = context.lookup;
let lookup;
@@ -17,16 +18,30 @@ moduleFor(
context.lookup = originalLookup;
}
- ['@test it should return false if no target or action are specified'](assert) {
- assert.expect(1);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test it should return false if no target or action are specified`](assert) {
+ assert.expect(2);
+
+ expectDeprecation(
+ /Calling `triggerAction` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
let obj = EmberObject.extend(TargetActionSupport).create();
assert.ok(false === obj.triggerAction(), 'no target or action was specified');
}
- ['@test it should support actions specified as strings'](assert) {
- assert.expect(2);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test it should support actions specified as strings`](assert) {
+ assert.expect(3);
+
+ expectDeprecation(
+ /Calling `triggerAction` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
let obj = EmberObject.extend(TargetActionSupport).create({
target: EmberObject.create({
@@ -41,8 +56,15 @@ moduleFor(
assert.ok(true === obj.triggerAction(), 'a valid target and action were specified');
}
- ['@test it should invoke the send() method on objects that implement it'](assert) {
- assert.expect(3);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test it should invoke the send() method on objects that implement it`](assert) {
+ assert.expect(4);
+
+ expectDeprecation(
+ /Calling `triggerAction` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
let obj = EmberObject.extend(TargetActionSupport).create({
target: EmberObject.create({
@@ -58,8 +80,15 @@ moduleFor(
assert.ok(true === obj.triggerAction(), 'a valid target and action were specified');
}
- ['@test it should find targets specified using a property path'](assert) {
- assert.expect(2);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test it should find targets specified using a property path`](assert) {
+ assert.expect(3);
+
+ expectDeprecation(
+ /Calling `triggerAction` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
let Test = {};
lookup.Test = Test;
@@ -78,8 +107,16 @@ moduleFor(
assert.ok(true === myObj.triggerAction(), 'a valid target and action were specified');
}
- ['@test it should use an actionContext object specified as a property on the object'](assert) {
- assert.expect(2);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test it should use an actionContext object specified as a property on the object`](assert) {
+ assert.expect(3);
+
+ expectDeprecation(
+ /Calling `triggerAction` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
+
let obj = EmberObject.extend(TargetActionSupport).create({
action: 'anEvent',
actionContext: {},
@@ -92,11 +129,19 @@ moduleFor(
},
}),
});
+
assert.ok(true === obj.triggerAction(), 'a valid target and action were specified');
}
- ['@test it should find an actionContext specified as a property path'](assert) {
- assert.expect(2);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test it should find an actionContext specified as a property path`](assert) {
+ assert.expect(3);
+
+ expectDeprecation(
+ /Calling `triggerAction` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
let Test = {};
lookup.Test = Test;
@@ -115,8 +160,16 @@ moduleFor(
assert.ok(true === obj.triggerAction(), 'a valid target and action were specified');
}
- ['@test it should use the target specified in the argument'](assert) {
- assert.expect(2);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test it should use the target specified in the argument`](assert) {
+ assert.expect(3);
+
+ expectDeprecation(
+ /Calling `triggerAction` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
+
let targetObj = EmberObject.create({
anEvent() {
assert.ok(true, 'anEvent method was called');
@@ -132,8 +185,15 @@ moduleFor(
);
}
- ['@test it should use the action specified in the argument'](assert) {
- assert.expect(2);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test it should use the action specified in the argument`](assert) {
+ assert.expect(3);
+
+ expectDeprecation(
+ /Calling `triggerAction` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
let obj = EmberObject.extend(TargetActionSupport).create({
target: EmberObject.create({
@@ -142,14 +202,23 @@ moduleFor(
},
}),
});
+
assert.ok(
true === obj.triggerAction({ action: 'anEvent' }),
'a valid target and action were specified'
);
}
- ['@test it should use the actionContext specified in the argument'](assert) {
- assert.expect(2);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test it should use the actionContext specified in the argument`](assert) {
+ assert.expect(3);
+
+ expectDeprecation(
+ /Calling `triggerAction` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
+
let context = {};
let obj = EmberObject.extend(TargetActionSupport).create({
target: EmberObject.create({
@@ -166,8 +235,16 @@ moduleFor(
);
}
- ['@test it should allow multiple arguments from actionContext'](assert) {
- assert.expect(3);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test it should allow multiple arguments from actionContext`](assert) {
+ assert.expect(4);
+
+ expectDeprecation(
+ /Calling `triggerAction` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
+
let param1 = 'someParam';
let param2 = 'someOtherParam';
let obj = EmberObject.extend(TargetActionSupport).create({
@@ -192,8 +269,16 @@ moduleFor(
);
}
- ['@test it should use a null value specified in the actionContext argument'](assert) {
- assert.expect(2);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test it should use a null value specified in the actionContext argument`](assert) {
+ assert.expect(3);
+
+ expectDeprecation(
+ /Calling `triggerAction` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
+
let obj = EmberObject.extend(TargetActionSupport).create({
target: EmberObject.create({
anEvent(ctx) {
@@ -202,6 +287,7 @@ moduleFor(
}),
action: 'anEvent',
});
+
assert.ok(
true === obj.triggerAction({ actionContext: null }),
'a valid target and action were specified'
diff --git a/packages/@ember/-internals/views/lib/mixins/action_support.ts b/packages/@ember/-internals/views/lib/mixins/action_support.ts
index a4c95d28ac3..08630d74d4e 100644
--- a/packages/@ember/-internals/views/lib/mixins/action_support.ts
+++ b/packages/@ember/-internals/views/lib/mixins/action_support.ts
@@ -5,6 +5,7 @@ import { get } from '@ember/-internals/metal/lib/property_get';
import Mixin from '@ember/object/mixin';
import inspect from '@ember/debug/lib/inspect';
import { assert } from '@ember/debug';
+import { deprecateUntil, DEPRECATIONS } from '@ember/-internals/deprecations';
/**
@class ActionSupport
@@ -16,6 +17,11 @@ interface ActionSupport {
}
const ActionSupport = Mixin.create({
send(actionName: string, ...args: unknown[]) {
+ deprecateUntil(
+ `Calling \`.send()\` on ${this} is deprecated. Invoke the corresponding method directly.`,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT
+ );
+
assert(
`Attempted to call .send() with the action '${actionName}' on the destroyed object '${this}'.`,
!this.isDestroying && !this.isDestroyed
diff --git a/packages/@ember/controller/tests/controller_test.js b/packages/@ember/controller/tests/controller_test.js
index 30afa631bee..3b9dc8ef131 100644
--- a/packages/@ember/controller/tests/controller_test.js
+++ b/packages/@ember/controller/tests/controller_test.js
@@ -3,8 +3,17 @@ import Service, { service } from '@ember/service';
import EmberObject, { get } from '@ember/object';
import Mixin from '@ember/object/mixin';
import { setOwner } from '@ember/-internals/owner';
-import { runDestroy, buildOwner } from 'internal-test-helpers';
-import { moduleFor, ApplicationTestCase, AbstractTestCase, runTask } from 'internal-test-helpers';
+import {
+ runDestroy,
+ buildOwner,
+ expectDeprecation,
+ moduleFor,
+ ApplicationTestCase,
+ AbstractTestCase,
+ runTask,
+ testUnless,
+} from 'internal-test-helpers';
+import { DEPRECATIONS } from '@ember/-internals/deprecations';
import { action } from '@ember/object';
import { precompileTemplate } from '@ember/template-compilation';
@@ -79,8 +88,16 @@ moduleFor(
moduleFor(
'Controller event handling',
class extends AbstractTestCase {
- ['@test Action can be handled by a function on actions object'](assert) {
- assert.expect(1);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test Action can be handled by a function on actions object`](assert) {
+ assert.expect(2);
+
+ expectDeprecation(
+ /Calling `\.send\(\)` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
+
let TestController = Controller.extend({
actions: {
poke() {
@@ -92,8 +109,16 @@ moduleFor(
controller.send('poke');
}
- ['@test A handled action can be bubbled to the target for continued processing'](assert) {
- assert.expect(2);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test A handled action can be bubbled to the target for continued processing`](assert) {
+ assert.expect(3);
+
+ expectDeprecation(
+ /Calling `\.send\(\)` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
+
let owner = buildOwner();
let TestController = Controller.extend({
@@ -124,8 +149,15 @@ moduleFor(
runDestroy(owner);
}
- ["@test Action can be handled by a superclass' actions object"](assert) {
- assert.expect(4);
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test Action can be handled by a superclass' actions object`](assert) {
+ assert.expect(5);
+
+ expectDeprecation(
+ /Calling `\.send\(\)` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
let SuperController = Controller.extend({
actions: {
@@ -161,7 +193,14 @@ moduleFor(
controller.send('baz');
}
- ['@test .send asserts if called on a destroyed controller']() {
+ [`${testUnless(
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved
+ )} @test .send asserts if called on a destroyed controller`]() {
+ expectDeprecation(
+ /Calling `\.send\(\)` on/,
+ DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled
+ );
+
let owner = buildOwner();
owner.register(
diff --git a/packages/ember/tests/routing/query_params_test.js b/packages/ember/tests/routing/query_params_test.js
index a95bdfe1bbc..9e2b729fe80 100644
--- a/packages/ember/tests/routing/query_params_test.js
+++ b/packages/ember/tests/routing/query_params_test.js
@@ -752,21 +752,14 @@ moduleFor(
);
this.setSingleQPController('application', 'foo', 1, {
+ router: service(),
increment: action(function () {
this.incrementProperty('foo');
- this.send('refreshRoute');
+ this.router.refresh();
}),
});
- this.add(
- 'route:application',
- class extends Route {
- @action
- refreshRoute() {
- this.refresh();
- }
- }
- );
+ this.add('route:application', Route);
await this.visitAndAssert('/');
assert.equal(getTextOf(document.getElementById('test-value')), '1');
diff --git a/packages/ember/tests/routing/router_service_test/non_application_test_test.js b/packages/ember/tests/routing/router_service_test/non_application_test_test.js
index 400f5b0cc6f..51b48ce57d8 100644
--- a/packages/ember/tests/routing/router_service_test/non_application_test_test.js
+++ b/packages/ember/tests/routing/router_service_test/non_application_test_test.js
@@ -109,7 +109,7 @@ moduleFor(
this.render('{{foo-bar}}');
run(function () {
- componentInstance.send('transitionToSister');
+ componentInstance.transitionToSister();
});
assert.equal(this.routerService.get('currentRouteName'), 'parent.sister');
diff --git a/packages/ember/tests/routing/router_service_test/transitionTo_test.js b/packages/ember/tests/routing/router_service_test/transitionTo_test.js
index 99ad4eb31c8..f9087a41b5d 100644
--- a/packages/ember/tests/routing/router_service_test/transitionTo_test.js
+++ b/packages/ember/tests/routing/router_service_test/transitionTo_test.js
@@ -124,7 +124,7 @@ moduleFor(
return this.visit('/').then(() => {
run(function () {
- componentInstance.send('transitionToSister');
+ componentInstance.transitionToSister();
});
assert.equal(this.routerService.get('currentRouteName'), 'parent.sister');
@@ -159,7 +159,7 @@ moduleFor(
return this.visit('/').then(() => {
run(function () {
- componentInstance.send('transitionToSister');
+ componentInstance.transitionToSister();
});
assert.equal(this.routerService.get('currentRouteName'), 'parent.sister');
@@ -197,7 +197,7 @@ moduleFor(
await this.visit('/');
run(function () {
- componentInstance.send('transitionToDynamic');
+ componentInstance.transitionToDynamic();
});
assert.equal(this.routerService.get('currentRouteName'), 'dynamic');
@@ -245,7 +245,7 @@ moduleFor(
await this.visit('/');
run(function () {
- componentInstance.send('transitionToDynamic');
+ componentInstance.transitionToDynamic();
});
assert.equal(this.routerService.get('currentRouteName'), 'dynamic');