From 87de0e59ebfe2c913d42bb9c5294cce5984c9c7a Mon Sep 17 00:00:00 2001 From: Peter Wagenet Date: Thu, 4 Sep 2025 08:14:26 -0700 Subject: [PATCH 1/9] Deprecate TargetActionSupport per RFC 1041 Implements emberjs/rfcs#1041: deprecates TargetActionSupport#triggerAction, ActionHandler#send, and ActionSupport#send under the single deprecation id deprecate-target-action-support, staged as available (not yet enabled) since the RFC is at the Accepted stage. Co-authored-by: Peter Wagenet --- .../@ember/-internals/deprecations/index.ts | 7 + .../components/target-action-test.js | 60 ++++++-- .../runtime/lib/mixins/action_handler.ts | 7 + .../lib/mixins/target_action_support.ts | 7 + .../mixins/target_action_support_test.js | 132 +++++++++++++++--- .../views/lib/mixins/action_support.ts | 6 + .../controller/tests/controller_test.js | 57 ++++++-- .../ember/tests/routing/query_params_test.js | 13 +- .../non_application_test_test.js | 2 +- .../router_service_test/transitionTo_test.js | 8 +- 10 files changed, 243 insertions(+), 56 deletions(-) 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..007f12cbad5 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 instead.`, + 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..d902845fbbe 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 instead.`, + 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..d6b6a833867 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 instead.`, + 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 0d0ab1db4cf..5fe6bb0cf12 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'); From 3ad67df76a9903f726177ad51b137515f7c9d851 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Fri, 24 Jul 2026 10:25:08 -0400 Subject: [PATCH 2/9] Deprecate the whole mixin --- .../runtime/lib/mixins/target_action_support.ts | 9 +++++++++ .../tests/mixins/target_action_support_test.js | 11 +++++++++++ 2 files changed, 20 insertions(+) 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 d902845fbbe..01e5f845c18 100644 --- a/packages/@ember/-internals/runtime/lib/mixins/target_action_support.ts +++ b/packages/@ember/-internals/runtime/lib/mixins/target_action_support.ts @@ -37,6 +37,15 @@ const TargetActionSupport = Mixin.create({ action: null, actionContext: null, + init: function () { + deprecateUntil( + `Extending from \`TargetActionSupport\` is deprecated.`, + DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT + ); + + return this._super(...arguments); + }, + actionContextObject: computed('actionContext', function () { let actionContext = get(this, 'actionContext'); 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 13fae5111ed..f0e79b2bb45 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 @@ -18,6 +18,17 @@ moduleFor( context.lookup = originalLookup; } + [`${testUnless( + DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved + )} @test it should return false if no target or action are specified`](assert) { + assert.expect(2); + + expectDeprecation( + /Extending from `TargetActionSupport` is deprecated/, + DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled + ); + } + [`${testUnless( DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved )} @test it should return false if no target or action are specified`](assert) { From 7dc33e77d155f96a3978ad14743f1dd1db94acc7 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Fri, 24 Jul 2026 10:38:20 -0400 Subject: [PATCH 3/9] Revert "Deprecate the whole mixin" This reverts commit 3ad67df76a9903f726177ad51b137515f7c9d851. --- .../runtime/lib/mixins/target_action_support.ts | 9 --------- .../tests/mixins/target_action_support_test.js | 11 ----------- 2 files changed, 20 deletions(-) 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 01e5f845c18..d902845fbbe 100644 --- a/packages/@ember/-internals/runtime/lib/mixins/target_action_support.ts +++ b/packages/@ember/-internals/runtime/lib/mixins/target_action_support.ts @@ -37,15 +37,6 @@ const TargetActionSupport = Mixin.create({ action: null, actionContext: null, - init: function () { - deprecateUntil( - `Extending from \`TargetActionSupport\` is deprecated.`, - DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT - ); - - return this._super(...arguments); - }, - actionContextObject: computed('actionContext', function () { let actionContext = get(this, 'actionContext'); 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 f0e79b2bb45..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 @@ -18,17 +18,6 @@ moduleFor( context.lookup = originalLookup; } - [`${testUnless( - DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved - )} @test it should return false if no target or action are specified`](assert) { - assert.expect(2); - - expectDeprecation( - /Extending from `TargetActionSupport` is deprecated/, - DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isEnabled - ); - } - [`${testUnless( DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT.isRemoved )} @test it should return false if no target or action are specified`](assert) { From 42bd6621d4338cbbe7036706eea60d7d3a151ba8 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Fri, 24 Jul 2026 13:00:40 -0400 Subject: [PATCH 4/9] Update packages/@ember/-internals/views/lib/mixins/action_support.ts Co-authored-by: Katie Gengler --- packages/@ember/-internals/views/lib/mixins/action_support.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@ember/-internals/views/lib/mixins/action_support.ts b/packages/@ember/-internals/views/lib/mixins/action_support.ts index d6b6a833867..08630d74d4e 100644 --- a/packages/@ember/-internals/views/lib/mixins/action_support.ts +++ b/packages/@ember/-internals/views/lib/mixins/action_support.ts @@ -18,7 +18,7 @@ interface ActionSupport { const ActionSupport = Mixin.create({ send(actionName: string, ...args: unknown[]) { deprecateUntil( - `Calling \`.send()\` on ${this} is deprecated. Invoke the corresponding method directly instead.`, + `Calling \`.send()\` on ${this} is deprecated. Invoke the corresponding method directly.`, DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT ); From fe6ba4291bf08bd4552b42a90ed5d35b2b8fc994 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Fri, 24 Jul 2026 13:00:47 -0400 Subject: [PATCH 5/9] Update packages/@ember/-internals/runtime/lib/mixins/target_action_support.ts Co-authored-by: Katie Gengler --- .../-internals/runtime/lib/mixins/target_action_support.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 d902845fbbe..6937ec312dd 100644 --- a/packages/@ember/-internals/runtime/lib/mixins/target_action_support.ts +++ b/packages/@ember/-internals/runtime/lib/mixins/target_action_support.ts @@ -112,7 +112,7 @@ const TargetActionSupport = Mixin.create({ */ triggerAction(opts: { action?: string; target?: unknown; actionContext?: unknown } = {}) { deprecateUntil( - `Calling \`triggerAction\` on ${this} is deprecated. Invoke the target method directly instead.`, + `Calling \`triggerAction\` on ${this} is deprecated. Invoke the target method directly.`, DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT ); From e1aa9182aa7e8f3cbe1b6593d3c9fbf0b35265d4 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Fri, 24 Jul 2026 13:00:54 -0400 Subject: [PATCH 6/9] Update packages/@ember/-internals/runtime/lib/mixins/action_handler.ts Co-authored-by: Katie Gengler --- packages/@ember/-internals/runtime/lib/mixins/action_handler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@ember/-internals/runtime/lib/mixins/action_handler.ts b/packages/@ember/-internals/runtime/lib/mixins/action_handler.ts index 007f12cbad5..116d52c8c3e 100644 --- a/packages/@ember/-internals/runtime/lib/mixins/action_handler.ts +++ b/packages/@ember/-internals/runtime/lib/mixins/action_handler.ts @@ -206,7 +206,7 @@ const ActionHandler = Mixin.create({ */ send(actionName: string, ...args: any[]) { deprecateUntil( - `Calling \`.send()\` on ${this} is deprecated. Invoke the corresponding method directly instead.`, + `Calling \`.send()\` on ${this} is deprecated. Invoke the corresponding method directly.`, DEPRECATIONS.DEPRECATE_TARGET_ACTION_SUPPORT ); assert( From 08a7fd9adbefdb3997288499979d55c5a18743c9 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Fri, 24 Jul 2026 13:06:42 -0400 Subject: [PATCH 7/9] Easier local testing of deprecations --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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', }); From eb039dbea8d9df9bab2fc24845aaf6229d7f17b8 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Fri, 24 Jul 2026 13:06:50 -0400 Subject: [PATCH 8/9] Enabled 7.4.0? --- packages/@ember/-internals/deprecations/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@ember/-internals/deprecations/index.ts b/packages/@ember/-internals/deprecations/index.ts index 9625d864bc5..545d0c3a5ad 100644 --- a/packages/@ember/-internals/deprecations/index.ts +++ b/packages/@ember/-internals/deprecations/index.ts @@ -122,7 +122,7 @@ export const DEPRECATIONS = { DEPRECATE_TARGET_ACTION_SUPPORT: deprecation({ for: 'ember-source', id: 'deprecate-target-action-support', - since: { available: '7.3.0' }, + since: { available: '7.3.0', enabled: '7.4.0' }, until: '8.0.0', url: 'https://deprecations.emberjs.com/id/deprecate-target-action-support', }), From db6cc1a9097ba636ce22aa2c06a18b76bce5ddae Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 27 Jul 2026 11:20:25 -0400 Subject: [PATCH 9/9] Update deprecation for target action support Removed the 'enabled' property from the deprecation since version. --- packages/@ember/-internals/deprecations/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@ember/-internals/deprecations/index.ts b/packages/@ember/-internals/deprecations/index.ts index 545d0c3a5ad..9625d864bc5 100644 --- a/packages/@ember/-internals/deprecations/index.ts +++ b/packages/@ember/-internals/deprecations/index.ts @@ -122,7 +122,7 @@ export const DEPRECATIONS = { DEPRECATE_TARGET_ACTION_SUPPORT: deprecation({ for: 'ember-source', id: 'deprecate-target-action-support', - since: { available: '7.3.0', enabled: '7.4.0' }, + since: { available: '7.3.0' }, until: '8.0.0', url: 'https://deprecations.emberjs.com/id/deprecate-target-action-support', }),