Skip to content

Deprecate PromiseProxyMixin, Enumerable, and Observable (mixins, RFC#… - #21588

Open
NullVoxPopuli wants to merge 1 commit into
mainfrom
nvp/deprecate-mixin-followups
Open

NullVoxPopuli wants to merge 1 commit into
mainfrom
nvp/deprecate-mixin-followups

Conversation

@NullVoxPopuli

@NullVoxPopuli NullVoxPopuli commented Aug 31, 2026 •

Copy link
Copy Markdown
Contributor

Supersedes:

Advancement:

RFC:

Guides:

Best viewed with:
image

Note

Because of the strategy of this deprecation (internal + public extends + deprecate), our tests don't have a lot of the testUnless stuff. We still need the tests because many of these mixins are still used internally. This makes this deprecation a bit different from the other ones due to how entangled mixins our in the codebase

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is weird, sure, but also trying to deprecate all this stuff, while heavily used internally, and not throwing deprecations on it is difficult -- I'm super looking forward to the cleanup for v8

@github-actions

github-actions Bot commented Aug 31, 2026 •

Copy link
Copy Markdown
Contributor

📊 Size report

Tarball size — 1.2 MB → 1.2 MB

dist/dev   0.6%↑

File Before (Size / Brotli) After (Size / Brotli)
Total (Includes all files) 2.1 MB / 508 kB 0.6%↑2.1 MB / 0.8%↑511.9 kB
Show files (29 files)
File Before (Size / Brotli) After (Size / Brotli)
./packages/@ember/-internals/deprecations/index.js 6.5 kB / 1.7 kB 44%↑9.4 kB / 12%↑1.9 kB
./packages/@ember/-internals/runtime/lib/mixins/-proxy-internal.js — 4 kB / 1.3 kB
./packages/@ember/-internals/runtime/lib/mixins/-proxy.js 4 kB / 1.3 kB -76.7%↓935 B / -69.6%↓408 B
./packages/@ember/-internals/runtime/lib/mixins/action_handler-internal.js — 1.6 kB / 598 B
./packages/@ember/-internals/runtime/lib/mixins/action_handler.js 6.2 kB / 1.7 kB -11.3%↓5.5 kB / -14%↓1.5 kB
./packages/@ember/-internals/runtime/lib/mixins/container_proxy-internal.js — 990 B / 358 B
./packages/@ember/-internals/runtime/lib/mixins/container_proxy.js 1.2 kB / 421 B -10%↓1.1 kB / -7.6%↓389 B
./packages/@ember/-internals/runtime/lib/mixins/registry_proxy-internal.js — 1.6 kB / 541 B
./packages/@ember/-internals/runtime/lib/mixins/registry_proxy.js 1.6 kB / 566 B -48.1%↓806 B / -45.1%↓311 B
./packages/@ember/-internals/runtime/lib/mixins/target_action_support-internal.js — 2.8 kB / 836 B
./packages/@ember/-internals/runtime/lib/mixins/target_action_support.js 4.9 kB / 1.3 kB -77.9%↓1.1 kB / -68.3%↓427 B
./packages/@ember/-internals/views/lib/mixins/action_support-internal.js — 1.7 kB / 631 B
./packages/@ember/-internals/views/lib/mixins/action_support.js 1.5 kB / 623 B -56%↓680 B / -51%↓305 B
./packages/@ember/array/index-internal.js — 15 kB / 3.6 kB
./packages/@ember/array/index.js 17.5 kB / 4.4 kB -76.3%↓4.1 kB / -71.5%↓1.2 kB
./packages/@ember/controller/controller-internal.js — 2.9 kB / 1 kB
./packages/@ember/controller/index.js 4.9 kB / 1.6 kB -41.9%↓2.8 kB / -41.2%↓939 B
./packages/@ember/enumerable/-internal.js — 416 B / 207 B
./packages/@ember/enumerable/index.js 570 B / 280 B 65%↑939 B / 44%↑403 B
./packages/@ember/enumerable/mutable-internal.js — 504 B / 230 B
./packages/@ember/enumerable/mutable.js 623 B / 289 B 57%↑981 B / 38%↑399 B
./packages/@ember/object/mixin-internal.js — 17 kB / 4.5 kB
./packages/@ember/object/mixin.js 610 B / 229 B 342%↑2.7 kB / 255%↑813 B
./packages/@ember/object/observable-internal.js — 4.4 kB / 1.1 kB
./packages/@ember/object/observable.js 6.7 kB / 1.8 kB -54.2%↓3.1 kB / -43%↓1 kB
./packages/shared-chunks/computed-DAHDiajo.js 34.1 kB / 7.9 kB —
./packages/shared-chunks/evented-{hash}.js 3.3 kB / 856 B 6%↑3.5 kB / 856 B
./packages/shared-chunks/mixin-WcybriNC.js 18.5 kB / 4.8 kB —
./packages/shared-chunks/properties-DEHxCEgs.js — 34.1 kB / 7.9 kB

dist/prod   0.6%↑

File Before (Size / Brotli) After (Size / Brotli)
Total (Includes all files) 1.9 MB / 464.7 kB 0.6%↑1.9 MB / 0.9%↑468.8 kB
Show files (29 files)
File Before (Size / Brotli) After (Size / Brotli)
./packages/@ember/-internals/deprecations/index.js 6.2 kB / 1.6 kB 46%↑9 kB / 12%↑1.8 kB
./packages/@ember/-internals/runtime/lib/mixins/-proxy-internal.js — 3.1 kB / 1.1 kB
./packages/@ember/-internals/runtime/lib/mixins/-proxy.js 3.1 kB / 1 kB -69.4%↓935 B / -60.6%↓408 B
./packages/@ember/-internals/runtime/lib/mixins/action_handler-internal.js — 1.1 kB / 462 B
./packages/@ember/-internals/runtime/lib/mixins/action_handler.js 5.7 kB / 1.6 kB -4.18%↓5.5 kB / -6.93%↓1.5 kB
./packages/@ember/-internals/runtime/lib/mixins/container_proxy-internal.js — 990 B / 358 B
./packages/@ember/-internals/runtime/lib/mixins/container_proxy.js 1.2 kB / 421 B -10%↓1.1 kB / -7.6%↓389 B
./packages/@ember/-internals/runtime/lib/mixins/registry_proxy-internal.js — 1.4 kB / 508 B
./packages/@ember/-internals/runtime/lib/mixins/registry_proxy.js 1.3 kB / 473 B -38.4%↓806 B / -34.3%↓311 B
./packages/@ember/-internals/runtime/lib/mixins/target_action_support-internal.js — 2.5 kB / 749 B
./packages/@ember/-internals/runtime/lib/mixins/target_action_support.js 4.6 kB / 1.3 kB -77.4%↓1 kB / -68.1%↓411 B
./packages/@ember/-internals/views/lib/mixins/action_support-internal.js — 1.1 kB / 463 B
./packages/@ember/-internals/views/lib/mixins/action_support.js 923 B / 411 B -26.3%↓680 B / -25.8%↓305 B
./packages/@ember/array/index-internal.js — 13.2 kB / 3.3 kB
./packages/@ember/array/index.js 15.7 kB / 4.1 kB -73.7%↓4.1 kB / -69.7%↓1.2 kB
./packages/@ember/controller/controller-internal.js — 2.9 kB / 1 kB
./packages/@ember/controller/index.js 4.9 kB / 1.6 kB -41.9%↓2.8 kB / -41.5%↓939 B
./packages/@ember/enumerable/-internal.js — 416 B / 207 B
./packages/@ember/enumerable/index.js 570 B / 280 B 65%↑939 B / 44%↑403 B
./packages/@ember/enumerable/mutable-internal.js — 504 B / 230 B
./packages/@ember/enumerable/mutable.js 623 B / 288 B 57%↑981 B / 39%↑399 B
./packages/@ember/object/mixin-internal.js — 15.3 kB / 4 kB
./packages/@ember/object/mixin.js 497 B / 204 B 443%↑2.7 kB / 299%↑813 B
./packages/@ember/object/observable-internal.js — 3.9 kB / 1 kB
./packages/@ember/object/observable.js 6.2 kB / 1.7 kB -50.4%↓3.1 kB / -39.4%↓1 kB
./packages/shared-chunks/computed-Cba9Q9-y.js 28.2 kB / 6.6 kB —
./packages/shared-chunks/evented-{hash}.js 3.3 kB / 854 B 6%↑3.5 kB / 854 B
./packages/shared-chunks/mixin-VFkcKfyP.js 16.7 kB / 4.4 kB —
./packages/shared-chunks/properties-_j6bSJnd.js — 28.2 kB / 6.6 kB

smoke-tests/v2-app-template/dist   1%↑

File Before (Size / Brotli) After (Size / Brotli)
./assets/main-{hash}.js 320.7 kB / 85.9 kB 0.7%↑323.1 kB / 0.3%↑86.2 kB
./assets/modules-{hash}.js 30.3 kB / 9.4 kB 7%↑32.6 kB / 4%↑9.8 kB
Total (Includes all files) 352.9 kB / 96.2 kB 1%↑357.5 kB / 0.6%↑96.8 kB

smoke-tests/v2-app-hello-world-template/dist   -1.87%↓

File Before (Size / Brotli) After (Size / Brotli)
./assets/main-{hash}.js 135.6 kB / 37.8 kB -1.87%↓133.1 kB / -1.84%↓37.1 kB
Total (Includes all files) 135.9 kB / 38 kB -1.87%↓133.4 kB / -1.84%↓37.3 kB

🤖 This report was automatically generated by wyvox/pkg-size

Comment thread packages/@ember/object/index.ts Outdated
class EmberObject extends CoreObject {
static {
// `extend(Observable)` would fire the Observable deprecation for every app.
this.PrototypeMixin.reopen(Observable);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm 🤷 on if these should us the public copies or not

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we will be deleting the public code ahead of when we cleanup our own code, so perhaps the way this is is better

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for how big this change, I 100% think we should rely on the existing tests as much as we can

send(actionName: string, ...args: unknown[]): void;
}
const ActionSupport = Mixin[INTERNAL_MIXIN_CREATE]({
send(actionName: string, ...args: unknown[]) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this deprecation does still exist in the internal copy

@NullVoxPopuli
NullVoxPopuli marked this pull request as draft September 2, 2026 17:38
Comment thread rollup.config.mjs

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't want to expose all these new internal files as importable things, so they got filtered out

@NullVoxPopuli
NullVoxPopuli marked this pull request as ready for review September 3, 2026 14:03
Comment thread packages/@ember/-internals/deprecations/index.ts

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated to 7.5

@property content
@type {unknown}
@default null
@public

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@public sounds wrong

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ye fixed

}

const ProxyMixin = /*@__PURE__*/ Mixin[INTERNAL_MIXIN_CREATE]({
const ProxyMixin = /*@__PURE__*/ DeprecatedMixin.create(InternalProxyMixin, {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prob want to add @deprecated to the yuidoc above

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

init() {
this._super(...arguments);
deprecateUntil(
'The `ActionHandler` mixin is deprecated. Use the `@action` decorator and direct method calls instead.',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we already handled this with TargetActionSupport deprecation and it is private above so it is possible this can be until 7.9.0 (through one LTS)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

return this.__container__.factoryFor(fullName);
init() {
this._super(...arguments);
deprecateUntil(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again since this was private the deprecation can be until 7.9

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tyty

const RegistryProxyMixin = DeprecatedMixin.create(InternalRegistryProxyMixin, {
init() {
this._super(...arguments);
deprecateUntil(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another that can be until 7.9

sorry for doing all as comments but github is being so slow I don't trust review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tyty <3

Comment thread packages/@ember/array/index-internal.ts Outdated
@static
@for @ember/array
@return {Ember.NativeArray}
@public

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be marked public?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should not, thank you

let value = get(controller, prop);
delegate(prop, value);
deprecateUntil(
'The `ControllerMixin` mixin is deprecated. Extend `Controller` from `@ember/controller` instead.',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mixin was private so the deprecation can be until 7.9

For the private mixins, if they weren't importable they don't even need deprecations

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they were all importable :(

const Enumerable = DeprecatedMixin.create(InternalEnumerable, {
init() {
this._super(...arguments);
deprecateUntil(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same re: private mixins

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

init() {
this._super(...arguments);
deprecateUntil(
'The `MutableEnumerable` mixin is deprecated. Use native arrays and array methods instead.',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and again

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

init() {
this._super(...arguments);
deprecateUntil(
'The `Evented` mixin is deprecated. Use native JavaScript events or a dedicated event library instead.',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the methods already have deprecations and the docs are makred as @deprecated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they did not log deprecations for deprecation-workflow tho

@public
*/
static create<M extends typeof Mixin>(...args: any[]): InstanceType<M> {
static override create<M extends typeof InternalMixin>(...args: any[]): InstanceType<M> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docs above need @deprecated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@NullVoxPopuli
NullVoxPopuli force-pushed the nvp/deprecate-mixin-followups branch from b19e196 to 27efb8f Compare September 29, 2026 18:32
RFC #1116 deprecates applying Ember's mixins, but Ember's own internals are
built on several of them. Those mixins need to exist twice: an internal copy
that applies silently, and a public copy that emits the deprecation.

This is the mechanical half -- the six mixins under @ember/-internals move to
`-internal` filenames with their contents unchanged, and their importers
follow. The public, deprecating copies are added in the next commit.

Add deprecating public mixin wrappers (RFC #1116 follow-up)

Every mixin Ember applies to its own classes now exists twice: the internal
copy applies silently, and the public copy wraps it and emits the deprecation
from `init`. The public copies keep the API documentation; the internal copies
carry the implementation.

`Mixin` itself gets the same treatment -- `InternalMixin` holds the machinery
and `Mixin.create` is the deprecating subclass -- which lets the
`INTERNAL_MIXIN_CREATE` symbol go away entirely.

Because the two copies are distinct objects, `meta.hasMixin` would no longer
match a public mixin against an object that only ever had the internal copy
applied. `DeprecatedMixin` overrides `detect` to look through to the wrapped
copy, so `EmberArray.detect(someArrayProxy)` keeps working while the
deprecation is live.

Ember's own tests that exercise a mixin's behavior now apply the internal copy,
matching what the framework does; tests that specifically cover the deprecation
keep using the public copy. `EmberObject` already applies the internal
`Observable`, so `observable_test` no longer re-applies the public one on top.

The internal copies are kept out of `renamed-modules` so they are not
advertised as importable module paths.

Move deprecations to 7.5

Set deprecate flags, and update untils
@NullVoxPopuli
NullVoxPopuli force-pushed the nvp/deprecate-mixin-followups branch from 27efb8f to 8ed880e Compare September 29, 2026 19:29

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants