From 3e6c2dacc391dc054ea876e5d5a086071423b905 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Thu, 10 Sep 2026 23:01:27 -0400 Subject: [PATCH 01/26] Placeholder files for the guides for https://github.com/emberjs/ember.js/pull/21588 --- content/ember/v7/deprecate-action-handler-mixin.md | 0 content/ember/v7/deprecate-array-proxy.md | 0 content/ember/v7/deprecate-container-proxy-mixin.md | 0 content/ember/v7/deprecate-controller-mixin.md | 0 content/ember/v7/deprecate-ember-array-mixin.md | 0 .../v7/{deprecate-enumerable.md => deprecate-enumerable-mixin.md} | 0 content/ember/v7/deprecate-mutable-enumerable-mixin.md | 0 content/ember/v7/deprecate-native-array-mixin.md | 0 content/ember/v7/deprecate-object-proxy.md | 0 content/ember/v7/deprecate-observable-mixin.md | 0 content/ember/v7/deprecate-registry-proxy-mixin.md | 0 11 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 content/ember/v7/deprecate-action-handler-mixin.md create mode 100644 content/ember/v7/deprecate-array-proxy.md create mode 100644 content/ember/v7/deprecate-container-proxy-mixin.md create mode 100644 content/ember/v7/deprecate-controller-mixin.md create mode 100644 content/ember/v7/deprecate-ember-array-mixin.md rename content/ember/v7/{deprecate-enumerable.md => deprecate-enumerable-mixin.md} (100%) create mode 100644 content/ember/v7/deprecate-mutable-enumerable-mixin.md create mode 100644 content/ember/v7/deprecate-native-array-mixin.md create mode 100644 content/ember/v7/deprecate-object-proxy.md create mode 100644 content/ember/v7/deprecate-observable-mixin.md create mode 100644 content/ember/v7/deprecate-registry-proxy-mixin.md diff --git a/content/ember/v7/deprecate-action-handler-mixin.md b/content/ember/v7/deprecate-action-handler-mixin.md new file mode 100644 index 000000000..e69de29bb diff --git a/content/ember/v7/deprecate-array-proxy.md b/content/ember/v7/deprecate-array-proxy.md new file mode 100644 index 000000000..e69de29bb diff --git a/content/ember/v7/deprecate-container-proxy-mixin.md b/content/ember/v7/deprecate-container-proxy-mixin.md new file mode 100644 index 000000000..e69de29bb diff --git a/content/ember/v7/deprecate-controller-mixin.md b/content/ember/v7/deprecate-controller-mixin.md new file mode 100644 index 000000000..e69de29bb diff --git a/content/ember/v7/deprecate-ember-array-mixin.md b/content/ember/v7/deprecate-ember-array-mixin.md new file mode 100644 index 000000000..e69de29bb diff --git a/content/ember/v7/deprecate-enumerable.md b/content/ember/v7/deprecate-enumerable-mixin.md similarity index 100% rename from content/ember/v7/deprecate-enumerable.md rename to content/ember/v7/deprecate-enumerable-mixin.md diff --git a/content/ember/v7/deprecate-mutable-enumerable-mixin.md b/content/ember/v7/deprecate-mutable-enumerable-mixin.md new file mode 100644 index 000000000..e69de29bb diff --git a/content/ember/v7/deprecate-native-array-mixin.md b/content/ember/v7/deprecate-native-array-mixin.md new file mode 100644 index 000000000..e69de29bb diff --git a/content/ember/v7/deprecate-object-proxy.md b/content/ember/v7/deprecate-object-proxy.md new file mode 100644 index 000000000..e69de29bb diff --git a/content/ember/v7/deprecate-observable-mixin.md b/content/ember/v7/deprecate-observable-mixin.md new file mode 100644 index 000000000..e69de29bb diff --git a/content/ember/v7/deprecate-registry-proxy-mixin.md b/content/ember/v7/deprecate-registry-proxy-mixin.md new file mode 100644 index 000000000..e69de29bb From 3311e7513d0b5cd2009b92209cf0e2434bda522d Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Fri, 11 Sep 2026 10:38:12 -0400 Subject: [PATCH 02/26] Write the guides for https://github.com/emberjs/ember.js/pull/21588 --- .../v7/deprecate-action-handler-mixin.md | 51 +++++ content/ember/v7/deprecate-array-proxy.md | 192 ++++++++++++++++++ .../v7/deprecate-container-proxy-mixin.md | 28 +++ .../ember/v7/deprecate-controller-mixin.md | 35 ++++ .../ember/v7/deprecate-ember-array-mixin.md | 86 ++++++++ .../ember/v7/deprecate-mutable-array-mixin.md | 71 +++++++ .../v7/deprecate-mutable-enumerable-mixin.md | 33 +++ .../ember/v7/deprecate-native-array-mixin.md | 41 ++++ content/ember/v7/deprecate-object-proxy.md | 183 +++++++++++++++++ .../ember/v7/deprecate-observable-mixin.md | 77 +++++++ content/ember/v7/deprecate-proxy-mixin.md | 55 +++++ .../v7/deprecate-registry-proxy-mixin.md | 13 ++ 12 files changed, 865 insertions(+) create mode 100644 content/ember/v7/deprecate-mutable-array-mixin.md create mode 100644 content/ember/v7/deprecate-proxy-mixin.md diff --git a/content/ember/v7/deprecate-action-handler-mixin.md b/content/ember/v7/deprecate-action-handler-mixin.md index e69de29bb..48da8bbab 100644 --- a/content/ember/v7/deprecate-action-handler-mixin.md +++ b/content/ember/v7/deprecate-action-handler-mixin.md @@ -0,0 +1,51 @@ +--- +title: 'ActionHandler mixin' +until: 8.0.0 +since: 7.4.0 +--- + +The `ActionHandler` mixin from `@ember/-internals/runtime` is deprecated. This mixin was private, but importable. + +`ActionHandler` gave an object an `actions` hash and a `send` method. Both are already deprecated on their own (refer to the [`send` deprecation](/id/deprecate-target-action-support)). The replacement is a plain method, decorated with `@action` when it is passed around as a callback. + +### Before + +```javascript +import EmberObject from '@ember/object'; +import { ActionHandler } from '@ember/-internals/runtime'; + +export default class Uploader extends EmberObject.extend(ActionHandler) { + actions = { + start(file) { + /* ... */ + }, + }; + + upload(file) { + this.send('start', file); + } +} +``` + +### After + +```javascript +import { action } from '@ember/object'; + +export default class Uploader { + @action + start(file) { + /* ... */ + } + + upload(file) { + this.start(file); + } +} +``` + +`@action` is only needed when the method is handed to something else (an `{{on}}` modifier, a child component argument, an event listener) and must keep its `this`. A method that is only called as `this.start()` does not need it. + +If the mixin was used for bubbling through `target`, pass the function down as an argument instead of naming it and bubbling by string. + +For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116). diff --git a/content/ember/v7/deprecate-array-proxy.md b/content/ember/v7/deprecate-array-proxy.md index e69de29bb..0a64e0bc0 100644 --- a/content/ember/v7/deprecate-array-proxy.md +++ b/content/ember/v7/deprecate-array-proxy.md @@ -0,0 +1,192 @@ +--- +title: 'ArrayProxy' +until: 8.0.0 +since: 7.4.0 +--- + +`ArrayProxy` from `@ember/array/proxy` is deprecated. Use a tracked array, or a plain array behind a `@tracked` property, instead. + +### Swapping the underlying array + +Before: + +```javascript +import ArrayProxy from '@ember/array/proxy'; +import { A } from '@ember/array'; + +let pets = ArrayProxy.create({ content: A(['dog', 'cat']) }); + +pets.get('firstObject'); // 'dog' + +pets.set('content', A(['amoeba'])); +pets.get('firstObject'); // 'amoeba' +``` + +After: + +```javascript +import { tracked } from '@glimmer/tracking'; + +class PetStore { + @tracked pets = ['dog', 'cat']; +} + +let store = new PetStore(); + +store.pets[0]; // 'dog' + +store.pets = ['amoeba']; +store.pets[0]; // 'amoeba' +``` + +### Mutating in place + +Before: + +```javascript +import ArrayProxy from '@ember/array/proxy'; +import { A } from '@ember/array'; + +let pets = ArrayProxy.create({ content: A(['dog', 'cat']) }); + +pets.pushObject('fish'); +pets.get('length'); // 3 +``` + +After: + +```javascript +import { trackedArray } from '@ember/reactive/collections'; + +let pets = trackedArray(['dog', 'cat']); + +pets.push('fish'); +pets.length; // 3 +``` + +`trackedArray` from [`@ember/reactive/collections`](https://api.emberjs.com/ember/release/modules/@ember%2Freactive%2Fcollections/) is a native array whose mutations are tracked. + +### Sorted or filtered views (`arrangedContent`) + +Before: + +```javascript +import ArrayProxy from '@ember/array/proxy'; +import { computed } from '@ember/object'; +import { A } from '@ember/array'; + +class SortedPeople extends ArrayProxy { + @computed('content.[]') + get arrangedContent() { + return this.content.sortBy('name'); + } +} + +let people = SortedPeople.create({ content: A([{ name: 'Yehuda' }, { name: 'Tom' }]) }); + +people.get('firstObject').name; // 'Tom' +``` + +After: + +```javascript +import { trackedArray } from '@ember/reactive/collections'; +import { cached } from '@glimmer/tracking'; + +class People { + all = trackedArray([{ name: 'Yehuda' }, { name: 'Tom' }]); + + @cached + get sorted() { + return this.all.toSorted((a, b) => a.name.localeCompare(b.name)); + } +} + +let people = new People(); + +people.sorted[0].name; // 'Tom' + +people.all.push({ name: 'Chris' }); +people.sorted[0].name; // 'Chris' +``` + +`@cached` is optional. Without it the getter re-sorts on every read, which is fine for small lists. + +### Transforming items (`objectAtContent`) + +Before: + +```javascript +import ArrayProxy from '@ember/array/proxy'; +import { A } from '@ember/array'; + +class ShoutingPets extends ArrayProxy { + objectAtContent(index) { + return this.content.objectAt(index).toUpperCase(); + } +} + +let pets = ShoutingPets.create({ content: A(['dog', 'cat']) }); + +pets.objectAt(0); // 'DOG' +``` + +After: + +```javascript +import { trackedArray } from '@ember/reactive/collections'; + +class Pets { + all = trackedArray(['dog', 'cat']); +} + +let pets = new Pets(); + +pets.all[0].toUpperCase(); // 'DOG' +pets.all.at(-1).toUpperCase(); // 'CAT' +``` + +### When you must keep a stable array-shaped object + +If a third-party consumer holds on to the object and expects it to act like an array while its contents are swapped, a native [`Proxy`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) over a tracked holder reproduces that: + +```javascript +import { tracked } from '@glimmer/tracking'; + +class Holder { + @tracked content; + + constructor(content) { + this.content = content; + } +} + +export function swappableArray(initial) { + let holder = new Holder(initial); + + return new Proxy(holder, { + get(target, key, receiver) { + if (key === 'content') return target.content; + return Reflect.get(target.content, key, receiver); + }, + set(target, key, value, receiver) { + if (key === 'content') { + target.content = value; + return true; + } + return Reflect.set(target.content, key, value, receiver); + }, + has: (target, key) => key in target.content, + ownKeys: (target) => Reflect.ownKeys(target.content), + getOwnPropertyDescriptor: (target, key) => Reflect.getOwnPropertyDescriptor(target.content, key), + }); +} +``` + +Treat this as a last resort. It is harder to debug than a tracked property and getter, and `Array.isArray` returns `false` for it. + +### Computed properties that depended on the proxy + +Computed properties with dependent keys such as `pets.[]` or `pets.@each.name` relied on `ArrayProxy` firing array change notifications. After migrating, convert those computed properties to native getters. Tracked arrays and tracked properties auto-track, so the dependent keys are no longer needed. + +For more background, read [RFC 1112](https://github.com/emberjs/rfcs/pull/1112). diff --git a/content/ember/v7/deprecate-container-proxy-mixin.md b/content/ember/v7/deprecate-container-proxy-mixin.md index e69de29bb..cbf977159 100644 --- a/content/ember/v7/deprecate-container-proxy-mixin.md +++ b/content/ember/v7/deprecate-container-proxy-mixin.md @@ -0,0 +1,28 @@ +--- +title: 'ContainerProxyMixin' +until: 8.0.0 +since: 7.4.0 +--- + +`ContainerProxyMixin` from `@ember/-internals/runtime` is deprecated. This mixin was private, but was importable. + +There is no migration for applying the mixin yourself. Remove it. If you built a custom object that forwarded to a container, look up what you need through the owner instead: + +```javascript +import { getOwner } from '@ember/owner'; + +class ThemeLoader { + constructor(owner) { + this.owner = owner; + } + + load(name) { + return this.owner.lookup(`theme:${name}`); + } +} + +// from anywhere with an owner +let loader = new ThemeLoader(getOwner(this)); +``` + +For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116). diff --git a/content/ember/v7/deprecate-controller-mixin.md b/content/ember/v7/deprecate-controller-mixin.md index e69de29bb..fdbbe4a34 100644 --- a/content/ember/v7/deprecate-controller-mixin.md +++ b/content/ember/v7/deprecate-controller-mixin.md @@ -0,0 +1,35 @@ +--- +title: 'ControllerMixin' +until: 8.0.0 +since: 7.4.0 +--- + +`ControllerMixin` from `@ember/controller` is deprecated. Extend `Controller` from the same module instead. `ControllerMixin` was private but was importable. + +### Before + +```javascript +// app/controllers/settings.js +import EmberObject from '@ember/object'; +import { ControllerMixin } from '@ember/controller'; + +export default class SettingsController extends EmberObject.extend(ControllerMixin) { + queryParams = ['tab']; + tab = 'general'; +} +``` + +### After + +```javascript +// app/controllers/settings.js +import Controller from '@ember/controller'; +import { tracked } from '@glimmer/tracking'; + +export default class SettingsController extends Controller { + queryParams = ['tab']; + @tracked tab = 'general'; +} +``` + +For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116). diff --git a/content/ember/v7/deprecate-ember-array-mixin.md b/content/ember/v7/deprecate-ember-array-mixin.md index e69de29bb..206444b82 100644 --- a/content/ember/v7/deprecate-ember-array-mixin.md +++ b/content/ember/v7/deprecate-ember-array-mixin.md @@ -0,0 +1,86 @@ +--- +title: 'EmberArray mixin' +until: 8.0.0 +since: 7.4.0 +--- + +The `EmberArray` mixin, the default export of `@ember/array`, is deprecated. Use native arrays and native array methods instead. + +`EmberArray` provided a read-only array API (`firstObject`, `objectAt`, `mapBy`, `filterBy`, `findBy`, `sortBy`, `uniq`, `compact`, `without`, and so on) for any object that exposed `length` and `objectAt`. Every one of those has a native equivalent. + +### Before: a custom array-like class + +```javascript +import EmberObject from '@ember/object'; +import EmberArray from '@ember/array'; + +export default class Pages extends EmberObject.extend(EmberArray) { + pages = []; + + get length() { + return this.pages.length; + } + + objectAt(index) { + return this.pages[index]; + } +} + +let pages = Pages.create({ pages: [{ title: 'Intro' }, { title: 'Setup' }] }); + +pages.get('firstObject').title; // 'Intro' +pages.mapBy('title'); // ['Intro', 'Setup'] +``` + +### After: a native array + +Most of the time the class only existed to give an array the Ember API. Drop the wrapper and use the array: + +```javascript +let pages = [{ title: 'Intro' }, { title: 'Setup' }]; + +pages[0].title; // 'Intro' +pages.map((page) => page.title); // ['Intro', 'Setup'] +``` + +If the collection drives UI updates, wrap it with `trackedArray` from [`@ember/reactive/collections`](https://api.emberjs.com/ember/release/modules/@ember%2Freactive%2Fcollections/) so mutations re-render: + +```javascript +import { trackedArray } from '@ember/reactive/collections'; + +let pages = trackedArray([{ title: 'Intro' }, { title: 'Setup' }]); +``` + +If the class has its own API and only needs to be iterable, implement the [iterable protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) instead: + +```javascript +export default class Pages { + #pages = []; + + *[Symbol.iterator]() { + yield* this.#pages; + } +} +``` + +### Replacing each method + +| EmberArray | Native | +| --- | --- | +| `firstObject`, `lastObject` | `arr[0]`, `arr.at(-1)` | +| `objectAt(i)`, `objectsAt([i, j])` | `arr[i]`, `[i, j].map((i) => arr[i])` | +| `mapBy('k')`, `getEach('k')` | `arr.map((x) => x.k)` | +| `filterBy('k', v)`, `rejectBy('k', v)` | `arr.filter((x) => x.k === v)`, `arr.filter((x) => x.k !== v)` | +| `findBy('k', v)` | `arr.find((x) => x.k === v)` | +| `isAny('k', v)`, `isEvery('k', v)` | `arr.some((x) => x.k === v)`, `arr.every((x) => x.k === v)` | +| `sortBy('k')` | `arr.toSorted((a, b) => compare(a.k, b.k))` with `compare` from `@ember/utils` | +| `uniq()`, `uniqBy('k')` | `Array.from(new Set(arr))`, `uniqBy` from `@ember/array` or a small helper | +| `compact()` | `arr.filter((x) => x != null)` | +| `without(x)` | `arr.filter((y) => y !== x)` | +| `invoke('m', ...args)` | `arr.map((x) => x.m(...args))` | +| `toArray()` | `Array.from(arr)` | +| `any(fn)`, `every(fn)`, `find(fn)`, `includes(x)` | same names on `Array.prototype` | + +Reactivity note: `sortBy`, `filterBy`, and friends were often used inside computed properties with `[]` or `@each` dependent keys. With tracked arrays, a plain getter that calls the native method re-computes on its own. + +For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116). diff --git a/content/ember/v7/deprecate-mutable-array-mixin.md b/content/ember/v7/deprecate-mutable-array-mixin.md new file mode 100644 index 000000000..f20cc6616 --- /dev/null +++ b/content/ember/v7/deprecate-mutable-array-mixin.md @@ -0,0 +1,71 @@ +--- +title: 'MutableArray mixin' +until: 8.0.0 +since: 7.4.0 +--- + +The `MutableArray` mixin, exported from `@ember/array` and `@ember/array/mutable`, is deprecated. Use native arrays and native array methods instead. + +`MutableArray` built on [`EmberArray`](/id/deprecate-ember-array-mixin) and added the mutation API: `pushObject`, `removeObject`, `insertAt`, `replace`, `clear`, and so on. These methods existed so the classic observer system could see array changes. With tracked arrays, native mutation is already observed. + +### Before: a custom mutable collection + +```javascript +import EmberObject from '@ember/object'; +import MutableArray from '@ember/array/mutable'; + +export default class Selection extends EmberObject.extend(MutableArray) { + items = []; + + get length() { + return this.items.length; + } + + objectAt(index) { + return this.items[index]; + } + + replace(start, deleteCount, added = []) { + this.items.splice(start, deleteCount, ...added); + this.arrayContentDidChange(start, deleteCount, added.length); + } +} + +let selection = Selection.create(); + +selection.pushObject('a'); +selection.addObject('a'); // no-op, already present +selection.removeObject('a'); +``` + +### After: a tracked array + +```javascript +import { trackedArray } from '@ember/reactive/collections'; + +let selection = trackedArray(); + +selection.push('a'); +if (!selection.includes('a')) selection.push('a'); +selection.splice(selection.indexOf('a'), 1); +``` + +Any template or getter that reads `selection` updates when it changes. If the values need to stay unique, `trackedSet` from the same module is a better fit than emulating `addObject`. + +### Replacing each method + +| MutableArray | Native | +| --- | --- | +| `pushObject(x)`, `pushObjects(arr)` | `arr.push(x)`, `arr.push(...items)` | +| `popObject()`, `shiftObject()` | `arr.pop()`, `arr.shift()` | +| `unshiftObject(x)`, `unshiftObjects(arr)` | `arr.unshift(x)`, `arr.unshift(...items)` | +| `insertAt(i, x)` | `arr.splice(i, 0, x)` | +| `removeAt(i, n)` | `arr.splice(i, n)` | +| `removeObject(x)`, `removeObjects(arr)` | `arr.splice(arr.indexOf(x), 1)`, or `removeAt` from `@ember/array` | +| `addObject(x)`, `addObjects(arr)` | `if (!arr.includes(x)) arr.push(x)`, or use a `trackedSet` | +| `replace(i, n, items)` | `arr.splice(i, n, ...items)` | +| `setObjects(items)` | `arr.splice(0, arr.length, ...items)` or assign a new array to a tracked property | +| `clear()` | `arr.length = 0` or `arr.splice(0)` | +| `reverseObjects()` | `arr.reverse()` | + +For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116). diff --git a/content/ember/v7/deprecate-mutable-enumerable-mixin.md b/content/ember/v7/deprecate-mutable-enumerable-mixin.md index e69de29bb..d6aaa4912 100644 --- a/content/ember/v7/deprecate-mutable-enumerable-mixin.md +++ b/content/ember/v7/deprecate-mutable-enumerable-mixin.md @@ -0,0 +1,33 @@ +--- +title: 'MutableEnumerable mixin' +until: 8.0.0 +since: 7.4.0 +--- + +`MutableEnumerable` from `@ember/enumerable/mutable` is deprecated. + +Like `Enumerable`, this mixin has been empty for a long time and was kept only so `.detect()` checks kept working. The migration is the same as for [`Enumerable`](/id/deprecate-enumerable-mixin): replace `.detect()` checks with `Array.isArray` or an iterable check, and replace custom collection classes with native arrays or `trackedArray`. + +### Before + +```javascript +import MutableEnumerable from '@ember/enumerable/mutable'; + +function clearAll(maybeList) { + if (MutableEnumerable.detect(maybeList)) { + maybeList.clear(); + } +} +``` + +### After + +```javascript +function clearAll(maybeList) { + if (Array.isArray(maybeList)) { + maybeList.length = 0; + } +} +``` + +For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116). diff --git a/content/ember/v7/deprecate-native-array-mixin.md b/content/ember/v7/deprecate-native-array-mixin.md index e69de29bb..8aaba97d5 100644 --- a/content/ember/v7/deprecate-native-array-mixin.md +++ b/content/ember/v7/deprecate-native-array-mixin.md @@ -0,0 +1,41 @@ +--- +title: 'NativeArray mixin' +until: 8.0.0 +since: 7.4.0 +--- + +The `NativeArray` mixin from `@ember/array` is deprecated. + +`NativeArray` is the set of [`EmberArray`](/id/deprecate-ember-array-mixin) and [`MutableArray`](/id/deprecate-mutable-array-mixin) methods that `A()` adds onto a plain JavaScript array. Using the mixin yourself now triggers this deprecation. Native arrays already have everything you need. Use them as-is, or wrap them with `trackedArray` when changes need to re-render. + +### Before + +```javascript +import { A, NativeArray } from '@ember/array'; + +let tags = A(['ember', 'glimmer']); + +tags.pushObject('vite'); +tags.get('lastObject'); // 'vite' + +NativeArray.detect(tags); // true +``` + +### After + +```javascript +import { trackedArray } from '@ember/reactive/collections'; + +let tags = trackedArray(['ember', 'glimmer']); + +tags.push('vite'); +tags.at(-1); // 'vite' + +Array.isArray(tags); // true +``` + +If the array never changes after creation, or only changes by reassignment of a `@tracked` property, a plain array literal is enough and `trackedArray` is not needed. + +Refer to the method tables in the [`EmberArray`](/id/deprecate-ember-array-mixin) and [`MutableArray`](/id/deprecate-mutable-array-mixin) guides for a native equivalent of each method. + +For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116). diff --git a/content/ember/v7/deprecate-object-proxy.md b/content/ember/v7/deprecate-object-proxy.md index e69de29bb..da12382d7 100644 --- a/content/ember/v7/deprecate-object-proxy.md +++ b/content/ember/v7/deprecate-object-proxy.md @@ -0,0 +1,183 @@ +--- +title: 'ObjectProxy' +until: 8.0.0 +since: 7.4.0 +--- + +`ObjectProxy` from `@ember/object/proxy` is deprecated. Use tracked properties and direct property access, or a native `Proxy` for the rare cases that need interception. + +`ObjectProxy` forwarded reads and writes of unknown properties to a `content` object. It was mostly used to swap that object out from under consumers, or to add computed properties on top of it. Tracked state covers both. + +Pick the section below that matches how you used it. + +### Swapping the wrapped object + +Before: + +```javascript +import ObjectProxy from '@ember/object/proxy'; + +let person = ObjectProxy.create({ content: { name: 'Tom' } }); + +person.get('name'); // 'Tom' + +person.set('content', { name: 'Thomas' }); +person.get('name'); // 'Thomas' +``` + +After: + +```javascript +import { tracked } from '@glimmer/tracking'; + +class CurrentUser { + @tracked person = { name: 'Tom' }; +} + +let current = new CurrentUser(); + +current.person.name; // 'Tom' + +current.person = { name: 'Thomas' }; +current.person.name; // 'Thomas' +``` + +Templates and getters that read `current.person.name` update when `person` is reassigned. + +### Adding properties on top of the wrapped object + +Before: + +```javascript +import ObjectProxy from '@ember/object/proxy'; +import { computed } from '@ember/object'; + +class PersonPresenter extends ObjectProxy { + @computed('firstName', 'lastName') + get fullName() { + return `${this.get('firstName')} ${this.get('lastName')}`; + } +} + +let presenter = PersonPresenter.create({ + content: { firstName: 'Tom', lastName: 'Dale' }, +}); + +presenter.get('fullName'); // 'Tom Dale' +presenter.get('firstName'); // 'Tom' +``` + +After, when you own the object, make it a class with the getter on it: + +```javascript +import { tracked } from '@glimmer/tracking'; + +class Person { + @tracked firstName; + @tracked lastName; + + constructor({ firstName, lastName }) { + this.firstName = firstName; + this.lastName = lastName; + } + + get fullName() { + return `${this.firstName} ${this.lastName}`; + } +} + +let person = new Person({ firstName: 'Tom', lastName: 'Dale' }); + +person.fullName; // 'Tom Dale' +person.firstName; // 'Tom' +``` + +After, when you do not own the object, wrap it in a class that exposes what you need: + +```javascript +import { tracked } from '@glimmer/tracking'; + +class PersonPresenter { + @tracked person; + + constructor(person) { + this.person = person; + } + + get fullName() { + return `${this.person.firstName} ${this.person.lastName}`; + } +} + +let presenter = new PersonPresenter({ firstName: 'Tom', lastName: 'Dale' }); + +presenter.fullName; // 'Tom Dale' +presenter.person.firstName; // 'Tom' +``` + +Reading `presenter.person.firstName` instead of `presenter.firstName` is the intended change. Explicit access is easier to type-check and to follow than forwarding. + +### Forwarding an open-ended set of properties + +If consumers read arbitrary keys through the wrapper and you cannot change them, a native [`Proxy`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) reproduces the forwarding: + +```javascript +let person = { firstName: 'Tom', lastName: 'Dale' }; + +let presenter = new Proxy(person, { + get(target, key, receiver) { + if (key === 'fullName') { + return `${target.firstName} ${target.lastName}`; + } + return Reflect.get(target, key, receiver); + }, +}); + +presenter.fullName; // 'Tom Dale' +presenter.firstName; // 'Tom' +``` + +To also swap the target later, keep the target in a `@tracked` property on a holder and forward through `target.content`, as shown in the [`ArrayProxy` guide](/id/deprecate-array-proxy). + +### `unknownProperty` and `setUnknownProperty` + +The `get` and `set` traps of a native `Proxy` are the direct replacement. + +Before: + +```javascript +import ObjectProxy from '@ember/object/proxy'; + +class Defaults extends ObjectProxy { + unknownProperty(key) { + return this.content[key] ?? `missing:${key}`; + } +} + +let settings = Defaults.create({ content: { theme: 'dark' } }); + +settings.get('theme'); // 'dark' +settings.get('locale'); // 'missing:locale' +``` + +After: + +```javascript +let settings = new Proxy( + { theme: 'dark' }, + { + get(target, key, receiver) { + return key in target ? Reflect.get(target, key, receiver) : `missing:${String(key)}`; + }, + } +); + +settings.theme; // 'dark' +settings.locale; // 'missing:locale' +``` + +### Computed properties that depended on the proxy + +Computed properties with dependent keys such as `content.firstName` relied on `ObjectProxy` notifying changes through `content`. After migrating, convert those computed properties to native getters. Tracked properties auto-track, so the dependent keys are no longer needed. + +For more background, read [RFC 1112](https://github.com/emberjs/rfcs/pull/1112). diff --git a/content/ember/v7/deprecate-observable-mixin.md b/content/ember/v7/deprecate-observable-mixin.md index e69de29bb..8a72d1eb2 100644 --- a/content/ember/v7/deprecate-observable-mixin.md +++ b/content/ember/v7/deprecate-observable-mixin.md @@ -0,0 +1,77 @@ +--- +title: 'Observable mixin' +until: 8.0.0 +since: 7.4.0 +--- + +The `Observable` mixin from `@ember/object/observable` is deprecated. + +`EmberObject` already includes this behavior, so the deprecation only fires when your code applies the mixin itself. That usually means one of two things: + +- a class that extends `EmberObject.extend(Observable)` (redundant, since `EmberObject` already has it) +- a class that applies `Observable` to get `get`, `set`, `notifyPropertyChange`, `addObserver`, `incrementProperty`, `toggleProperty`, and friends + +In both cases, the replacement is a native class with tracked properties and native property access. + +### Before + +```javascript +import EmberObject from '@ember/object'; +import Observable from '@ember/object/observable'; + +export default class Counter extends EmberObject.extend(Observable) { + count = 0; + + increment() { + this.incrementProperty('count'); + } + + reset() { + this.setProperties({ count: 0 }); + } +} + +let counter = Counter.create(); + +counter.get('count'); // 0 +counter.addObserver('count', () => console.log('changed')); +counter.increment(); +``` + +### After + +```javascript +import { tracked } from '@glimmer/tracking'; + +export default class Counter { + @tracked count = 0; + + increment() { + this.count++; + } + + reset() { + this.count = 0; + } +} + +let counter = new Counter(); + +counter.count; // 0 +counter.increment(); +``` + +Templates and getters that read `count` update automatically because the property is tracked. Nothing has to observe it. + +### Replacing each method + +| Observable method | Replacement | +| --- | --- | +| `get('foo')`, `getProperties(...)` | `this.foo` (refer to the [`get` and `set` deprecation](/id/deprecate-observable)) | +| `set('foo', v)`, `setProperties({...})` | `this.foo = v` on a `@tracked` property | +| `incrementProperty`, `decrementProperty`, `toggleProperty` | `this.foo++`, `this.foo--`, `this.foo = !this.foo` | +| `notifyPropertyChange` | Not needed. Assigning a tracked property invalidates dependents. | +| `addObserver`, `removeObserver` | Derive state with a getter instead of reacting to changes. Where a side effect is required, run it from the method that makes the change. | +| `cacheFor` | Not needed. Use `@cached` from `@glimmer/tracking` on a getter when you need memoization. | + +For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116). diff --git a/content/ember/v7/deprecate-proxy-mixin.md b/content/ember/v7/deprecate-proxy-mixin.md new file mode 100644 index 000000000..22f861052 --- /dev/null +++ b/content/ember/v7/deprecate-proxy-mixin.md @@ -0,0 +1,55 @@ +--- +title: 'ProxyMixin' +until: 8.0.0 +since: 7.4.0 +--- + +`ProxyMixin`, exported as `_ProxyMixin` from `@ember/-internals/runtime`, is deprecated. This mixin was private, but was importable. + +`ProxyMixin` is what gives [`ObjectProxy`](/id/deprecate-object-proxy) its behavior: every property not defined on the proxy is forwarded to `content`. Applying the mixin directly to another `EmberObject` subclass is deprecated along with `ObjectProxy` itself. + +### Before + +```javascript +import EmberObject from '@ember/object'; +import { _ProxyMixin } from '@ember/-internals/runtime'; + +export default class Draft extends EmberObject.extend(_ProxyMixin) { + isDraft = true; +} + +let draft = Draft.create({ content: { title: 'Hello' } }); + +draft.get('title'); // 'Hello' +draft.isDraft; // true +``` + +### After + +Most uses only need the wrapped object plus a few extra fields. Hold the object in a tracked property and read through it: + +```javascript +import { tracked } from '@glimmer/tracking'; + +export default class Draft { + @tracked content; + isDraft = true; + + constructor(content) { + this.content = content; + } + + get title() { + return this.content.title; + } +} + +let draft = new Draft({ title: 'Hello' }); + +draft.title; // 'Hello' +draft.isDraft; // true +``` + +When the forwarded property set is open-ended, a native `Proxy` covers the same ground. Refer to the [`ObjectProxy` deprecation](/id/deprecate-object-proxy) for that pattern and for `unknownProperty` replacements. + +For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116). diff --git a/content/ember/v7/deprecate-registry-proxy-mixin.md b/content/ember/v7/deprecate-registry-proxy-mixin.md index e69de29bb..debdce550 100644 --- a/content/ember/v7/deprecate-registry-proxy-mixin.md +++ b/content/ember/v7/deprecate-registry-proxy-mixin.md @@ -0,0 +1,13 @@ +--- +title: 'RegistryProxyMixin' +until: 8.0.0 +since: 7.4.0 +--- + +`RegistryProxyMixin` from `@ember/-internals/runtime` is deprecated. This mixin was private, but importable. + +The mixin gave `Application`, `Engine`, and their instances the registry methods: `register`, `unregister`, `resolveRegistration`, `hasRegistration`, `registerOption`, and friends. Ember still provides these methods on the owner. They now come from an internal copy of the mixin, so application code and initializers that call `application.register(...)` keep working without changes. + +There is no migration for applying the mixin yourself. Remove it. + +For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116). From c2ae8ce04692bcd22c5783e55e47cf367d187d19 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:21:26 -0400 Subject: [PATCH 03/26] Update content/ember/v7/deprecate-action-handler-mixin.md Co-authored-by: Katie Gengler --- content/ember/v7/deprecate-action-handler-mixin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ember/v7/deprecate-action-handler-mixin.md b/content/ember/v7/deprecate-action-handler-mixin.md index 48da8bbab..a868bb936 100644 --- a/content/ember/v7/deprecate-action-handler-mixin.md +++ b/content/ember/v7/deprecate-action-handler-mixin.md @@ -1,6 +1,6 @@ --- title: 'ActionHandler mixin' -until: 8.0.0 +until: 7.9.0 since: 7.4.0 --- From 6664327e0a816fa8818cc8809356262f42241f0b Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:21:34 -0400 Subject: [PATCH 04/26] Update content/ember/v7/deprecate-action-handler-mixin.md Co-authored-by: Katie Gengler --- content/ember/v7/deprecate-action-handler-mixin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ember/v7/deprecate-action-handler-mixin.md b/content/ember/v7/deprecate-action-handler-mixin.md index a868bb936..a4d0490e1 100644 --- a/content/ember/v7/deprecate-action-handler-mixin.md +++ b/content/ember/v7/deprecate-action-handler-mixin.md @@ -4,7 +4,7 @@ until: 7.9.0 since: 7.4.0 --- -The `ActionHandler` mixin from `@ember/-internals/runtime` is deprecated. This mixin was private, but importable. +The `ActionHandler` mixin from `@ember/-internals/runtime` is deprecated. This mixin was private but since it may have been used we have added a deprecation as a courtesy through the next LTS. `ActionHandler` gave an object an `actions` hash and a `send` method. Both are already deprecated on their own (refer to the [`send` deprecation](/id/deprecate-target-action-support)). The replacement is a plain method, decorated with `@action` when it is passed around as a callback. From f15912960fea4451ea3c675bf7da79d18ee7baa5 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:32:00 -0400 Subject: [PATCH 05/26] Update content/ember/v7/deprecate-action-handler-mixin.md Co-authored-by: Katie Gengler --- content/ember/v7/deprecate-action-handler-mixin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ember/v7/deprecate-action-handler-mixin.md b/content/ember/v7/deprecate-action-handler-mixin.md index a4d0490e1..b31a856bc 100644 --- a/content/ember/v7/deprecate-action-handler-mixin.md +++ b/content/ember/v7/deprecate-action-handler-mixin.md @@ -6,7 +6,7 @@ since: 7.4.0 The `ActionHandler` mixin from `@ember/-internals/runtime` is deprecated. This mixin was private but since it may have been used we have added a deprecation as a courtesy through the next LTS. -`ActionHandler` gave an object an `actions` hash and a `send` method. Both are already deprecated on their own (refer to the [`send` deprecation](/id/deprecate-target-action-support)). The replacement is a plain method, decorated with `@action` when it is passed around as a callback. +`ActionHandler` gave an object an `actions` hash and a `send` method. Both are already deprecated on their own (refer to the [`send` deprecation](/id/deprecate-target-action-support)). The replacement is a plain method, decorated with `@action` when it is passed around as a callback, for example to a modifier. ### Before From 3cd5f2f58255224088be2b73bcb48126037d4e66 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:42:05 -0400 Subject: [PATCH 06/26] Update content/ember/v7/deprecate-container-proxy-mixin.md Co-authored-by: Katie Gengler --- content/ember/v7/deprecate-container-proxy-mixin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ember/v7/deprecate-container-proxy-mixin.md b/content/ember/v7/deprecate-container-proxy-mixin.md index cbf977159..8c812721f 100644 --- a/content/ember/v7/deprecate-container-proxy-mixin.md +++ b/content/ember/v7/deprecate-container-proxy-mixin.md @@ -1,6 +1,6 @@ --- title: 'ContainerProxyMixin' -until: 8.0.0 +until: 7.9.0 since: 7.4.0 --- From e1d570150385cef3e4cef29d3478589c2d9168ef Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:42:13 -0400 Subject: [PATCH 07/26] Update content/ember/v7/deprecate-action-handler-mixin.md Co-authored-by: Katie Gengler --- content/ember/v7/deprecate-action-handler-mixin.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content/ember/v7/deprecate-action-handler-mixin.md b/content/ember/v7/deprecate-action-handler-mixin.md index b31a856bc..f5e050769 100644 --- a/content/ember/v7/deprecate-action-handler-mixin.md +++ b/content/ember/v7/deprecate-action-handler-mixin.md @@ -46,6 +46,8 @@ export default class Uploader { `@action` is only needed when the method is handed to something else (an `{{on}}` modifier, a child component argument, an event listener) and must keep its `this`. A method that is only called as `this.start()` does not need it. +This newer pattern can also be used in existing `EmberObject` classes and its descendents. + If the mixin was used for bubbling through `target`, pass the function down as an argument instead of naming it and bubbling by string. For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116). From 10346fc0779688b405590e515cfc17fd6b24000b Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:42:29 -0400 Subject: [PATCH 08/26] Update content/ember/v7/deprecate-container-proxy-mixin.md Co-authored-by: Katie Gengler --- content/ember/v7/deprecate-container-proxy-mixin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ember/v7/deprecate-container-proxy-mixin.md b/content/ember/v7/deprecate-container-proxy-mixin.md index 8c812721f..b90202efd 100644 --- a/content/ember/v7/deprecate-container-proxy-mixin.md +++ b/content/ember/v7/deprecate-container-proxy-mixin.md @@ -4,7 +4,7 @@ until: 7.9.0 since: 7.4.0 --- -`ContainerProxyMixin` from `@ember/-internals/runtime` is deprecated. This mixin was private, but was importable. +`ContainerProxyMixin` from `@ember/-internals/runtime` is deprecated. This mixin was private but since it may have been used we have added a deprecation as a courtesy through the next LTS. There is no migration for applying the mixin yourself. Remove it. If you built a custom object that forwarded to a container, look up what you need through the owner instead: From a7f733dea3fa49233e42a493148e35add062d11d Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:42:37 -0400 Subject: [PATCH 09/26] Update content/ember/v7/deprecate-controller-mixin.md Co-authored-by: Katie Gengler --- content/ember/v7/deprecate-controller-mixin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ember/v7/deprecate-controller-mixin.md b/content/ember/v7/deprecate-controller-mixin.md index fdbbe4a34..b466ebc6f 100644 --- a/content/ember/v7/deprecate-controller-mixin.md +++ b/content/ember/v7/deprecate-controller-mixin.md @@ -1,6 +1,6 @@ --- title: 'ControllerMixin' -until: 8.0.0 +until: 7.9.0 since: 7.4.0 --- From c59a208f604c263c1f19b7a19bbab4d3113fb744 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:42:47 -0400 Subject: [PATCH 10/26] Update content/ember/v7/deprecate-controller-mixin.md Co-authored-by: Katie Gengler --- content/ember/v7/deprecate-controller-mixin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ember/v7/deprecate-controller-mixin.md b/content/ember/v7/deprecate-controller-mixin.md index b466ebc6f..214e250f4 100644 --- a/content/ember/v7/deprecate-controller-mixin.md +++ b/content/ember/v7/deprecate-controller-mixin.md @@ -4,7 +4,7 @@ until: 7.9.0 since: 7.4.0 --- -`ControllerMixin` from `@ember/controller` is deprecated. Extend `Controller` from the same module instead. `ControllerMixin` was private but was importable. +`ControllerMixin` from `@ember/controller` is deprecated. Extend `Controller` from the same module instead. `ControllerMixin` was private but since it may have been used we have added a deprecation as a courtesy through the next LTS. ### Before From 16b13b7c8d6881c27e9314ec3558edf69d789efb Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:48:03 -0400 Subject: [PATCH 11/26] Update content/ember/v7/deprecate-mutable-array-mixin.md Co-authored-by: Katie Gengler --- content/ember/v7/deprecate-mutable-array-mixin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ember/v7/deprecate-mutable-array-mixin.md b/content/ember/v7/deprecate-mutable-array-mixin.md index f20cc6616..10dac34cf 100644 --- a/content/ember/v7/deprecate-mutable-array-mixin.md +++ b/content/ember/v7/deprecate-mutable-array-mixin.md @@ -6,7 +6,7 @@ since: 7.4.0 The `MutableArray` mixin, exported from `@ember/array` and `@ember/array/mutable`, is deprecated. Use native arrays and native array methods instead. -`MutableArray` built on [`EmberArray`](/id/deprecate-ember-array-mixin) and added the mutation API: `pushObject`, `removeObject`, `insertAt`, `replace`, `clear`, and so on. These methods existed so the classic observer system could see array changes. With tracked arrays, native mutation is already observed. +`MutableArray` built on [`EmberArray`](/id/deprecate-ember-array-mixin) and added the mutation API: `pushObject`, `removeObject`, `insertAt`, `replace`, `clear`, and so on. These methods existed so the classic reactivity system could see array changes. With tracked arrays, native mutation is already observed. ### Before: a custom mutable collection From 9df891614d5b22db20623c70b2434c3f67546de7 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:50:57 -0400 Subject: [PATCH 12/26] EnumerableMixin was renamed to match deprecation id, but private, so until needed to change to 7.9.0 --- content/ember/v7/deprecate-enumerable-mixin.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/content/ember/v7/deprecate-enumerable-mixin.md b/content/ember/v7/deprecate-enumerable-mixin.md index 97302eb68..a8735b2f4 100644 --- a/content/ember/v7/deprecate-enumerable-mixin.md +++ b/content/ember/v7/deprecate-enumerable-mixin.md @@ -1,10 +1,10 @@ --- -title: 'Enumerable and MutableEnumerable' -until: 8.0.0 +title: "Enumerable and MutableEnumerable" +until: 7.9.0 since: 7.4.0 --- -`Enumerable` from `@ember/enumerable` and `MutableEnumerable` from `@ember/enumerable/mutable` are deprecated. +`Enumerable` from `@ember/enumerable` and `MutableEnumerable` from `@ember/enumerable/mutable` are deprecated. This mixin was private but since it may have been used we have added a deprecation as a courtesy through the next LTS. These mixins have been empty for a long time. The mixins were kept only so that existing `.detect()` checks kept working. They are now deprecated along with the rest of the mixin system. @@ -15,7 +15,7 @@ These mixins have been empty for a long time. The mixins were kept only so that Before: ```javascript -import Enumerable from '@ember/enumerable'; +import Enumerable from "@ember/enumerable"; function printAll(maybeList) { if (Enumerable.detect(maybeList)) { @@ -38,7 +38,7 @@ Or, to accept any iterable (`Map`, `Set`, generators, and so on): ```javascript function printAll(maybeList) { - if (typeof maybeList?.[Symbol.iterator] === 'function') { + if (typeof maybeList?.[Symbol.iterator] === "function") { for (let item of maybeList) { console.log(item); } @@ -66,8 +66,8 @@ class Queue { } let queue = new Queue(); -queue.add('a'); -queue.add('b'); +queue.add("a"); +queue.add("b"); [...queue]; // ['a', 'b'] ``` From 5268566b0ab2847c6ad236989e8b2364bc66cb9c Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:52:16 -0400 Subject: [PATCH 13/26] Update content/ember/v7/deprecate-mutable-enumerable-mixin.md Co-authored-by: Katie Gengler --- content/ember/v7/deprecate-mutable-enumerable-mixin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ember/v7/deprecate-mutable-enumerable-mixin.md b/content/ember/v7/deprecate-mutable-enumerable-mixin.md index d6aaa4912..8b56059f5 100644 --- a/content/ember/v7/deprecate-mutable-enumerable-mixin.md +++ b/content/ember/v7/deprecate-mutable-enumerable-mixin.md @@ -1,6 +1,6 @@ --- title: 'MutableEnumerable mixin' -until: 8.0.0 +until: 7.9.0 since: 7.4.0 --- From 62dba8bcea28a1fd76134b8ee6d238f36ed2a8a2 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:52:25 -0400 Subject: [PATCH 14/26] Update content/ember/v7/deprecate-mutable-enumerable-mixin.md Co-authored-by: Katie Gengler --- content/ember/v7/deprecate-mutable-enumerable-mixin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ember/v7/deprecate-mutable-enumerable-mixin.md b/content/ember/v7/deprecate-mutable-enumerable-mixin.md index 8b56059f5..29a6fa6de 100644 --- a/content/ember/v7/deprecate-mutable-enumerable-mixin.md +++ b/content/ember/v7/deprecate-mutable-enumerable-mixin.md @@ -4,7 +4,7 @@ until: 7.9.0 since: 7.4.0 --- -`MutableEnumerable` from `@ember/enumerable/mutable` is deprecated. +`MutableEnumerable` from `@ember/enumerable/mutable` is deprecated. This mixin was private but since it may have been used we have added a deprecation as a courtesy through the next LTS. Like `Enumerable`, this mixin has been empty for a long time and was kept only so `.detect()` checks kept working. The migration is the same as for [`Enumerable`](/id/deprecate-enumerable-mixin): replace `.detect()` checks with `Array.isArray` or an iterable check, and replace custom collection classes with native arrays or `trackedArray`. From 007d9fb5f24202b82bf6f86bce367e6c89f46f49 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:55:19 -0400 Subject: [PATCH 15/26] Update content/ember/v7/deprecate-ember-array-mixin.md --- content/ember/v7/deprecate-ember-array-mixin.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/content/ember/v7/deprecate-ember-array-mixin.md b/content/ember/v7/deprecate-ember-array-mixin.md index 206444b82..77d3a3f27 100644 --- a/content/ember/v7/deprecate-ember-array-mixin.md +++ b/content/ember/v7/deprecate-ember-array-mixin.md @@ -83,4 +83,8 @@ export default class Pages { Reactivity note: `sortBy`, `filterBy`, and friends were often used inside computed properties with `[]` or `@each` dependent keys. With tracked arrays, a plain getter that calls the native method re-computes on its own. +As with any usage of the classic, pre-Octane system, there are interop considerations with `tracked`. Follow the [Octane migration guide](https://guides.emberjs.com/v5.7.0/upgrading/current-edition/tracked-properties/) to ensure you migrate in a safe manner. + +At this point, all of `EmberObject` included `computed` is planned to be deprecated under [RFC #1234](https://github.com/emberjs/rfcs/blob/main/text/1234-deprecate-ember-object.md) so fully moving to `tracked` is recommended. + For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116). From b2d3a4bb6ecc32465bb34d73a81b5664aface31d Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:59:09 -0400 Subject: [PATCH 16/26] Update content/ember/v7/deprecate-proxy-mixin.md Co-authored-by: Katie Gengler --- content/ember/v7/deprecate-proxy-mixin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ember/v7/deprecate-proxy-mixin.md b/content/ember/v7/deprecate-proxy-mixin.md index 22f861052..27226e8f9 100644 --- a/content/ember/v7/deprecate-proxy-mixin.md +++ b/content/ember/v7/deprecate-proxy-mixin.md @@ -4,7 +4,7 @@ until: 8.0.0 since: 7.4.0 --- -`ProxyMixin`, exported as `_ProxyMixin` from `@ember/-internals/runtime`, is deprecated. This mixin was private, but was importable. +`ProxyMixin`, exported as `_ProxyMixin` from `@ember/-internals/runtime`, is deprecated. This mixin was private but since it may have been used we have added a deprecation as a courtesy through the next LTS. `ProxyMixin` is what gives [`ObjectProxy`](/id/deprecate-object-proxy) its behavior: every property not defined on the proxy is forwarded to `content`. Applying the mixin directly to another `EmberObject` subclass is deprecated along with `ObjectProxy` itself. From 5892f969ab646cce3796ebca71a7100cf6e87e79 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:59:20 -0400 Subject: [PATCH 17/26] Update content/ember/v7/deprecate-mutable-array-mixin.md --- content/ember/v7/deprecate-mutable-array-mixin.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/content/ember/v7/deprecate-mutable-array-mixin.md b/content/ember/v7/deprecate-mutable-array-mixin.md index 10dac34cf..d134ddb18 100644 --- a/content/ember/v7/deprecate-mutable-array-mixin.md +++ b/content/ember/v7/deprecate-mutable-array-mixin.md @@ -68,4 +68,9 @@ Any template or getter that reads `selection` updates when it changes. If the va | `clear()` | `arr.length = 0` or `arr.splice(0)` | | `reverseObjects()` | `arr.reverse()` | + +As with any usage of the classic, pre-Octane system, there are interop considerations with `tracked`. Follow the [Octane migration guide](https://guides.emberjs.com/v5.7.0/upgrading/current-edition/tracked-properties/) to ensure you migrate in a safe manner. + +At this point, all of `EmberObject` included `computed` is planned to be deprecated under [RFC #1234](https://github.com/emberjs/rfcs/blob/main/text/1234-deprecate-ember-object.md) so fully moving to `tracked` is recommended. + For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116). From 91edb3ca6f6c7d2328c5034acb8a71f9ff15b6f1 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:59:30 -0400 Subject: [PATCH 18/26] Update content/ember/v7/deprecate-object-proxy.md --- content/ember/v7/deprecate-object-proxy.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/content/ember/v7/deprecate-object-proxy.md b/content/ember/v7/deprecate-object-proxy.md index da12382d7..ac73d60d8 100644 --- a/content/ember/v7/deprecate-object-proxy.md +++ b/content/ember/v7/deprecate-object-proxy.md @@ -180,4 +180,8 @@ settings.locale; // 'missing:locale' Computed properties with dependent keys such as `content.firstName` relied on `ObjectProxy` notifying changes through `content`. After migrating, convert those computed properties to native getters. Tracked properties auto-track, so the dependent keys are no longer needed. +As with any usage of the classic, pre-Octane system, there are interop considerations with `tracked`. Follow the [Octane migration guide](https://guides.emberjs.com/v5.7.0/upgrading/current-edition/tracked-properties/) to ensure you migrate in a safe manner. + +At this point, all of `EmberObject` included `computed` is planned to be deprecated under [RFC #1234](https://github.com/emberjs/rfcs/blob/main/text/1234-deprecate-ember-object.md) so fully moving to `tracked` is recommended. + For more background, read [RFC 1112](https://github.com/emberjs/rfcs/pull/1112). From 8030395cca607d5086ec399594f15b366b76ae04 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:59:40 -0400 Subject: [PATCH 19/26] Update content/ember/v7/deprecate-registry-proxy-mixin.md Co-authored-by: Katie Gengler --- content/ember/v7/deprecate-registry-proxy-mixin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ember/v7/deprecate-registry-proxy-mixin.md b/content/ember/v7/deprecate-registry-proxy-mixin.md index debdce550..58417285c 100644 --- a/content/ember/v7/deprecate-registry-proxy-mixin.md +++ b/content/ember/v7/deprecate-registry-proxy-mixin.md @@ -6,7 +6,7 @@ since: 7.4.0 `RegistryProxyMixin` from `@ember/-internals/runtime` is deprecated. This mixin was private, but importable. -The mixin gave `Application`, `Engine`, and their instances the registry methods: `register`, `unregister`, `resolveRegistration`, `hasRegistration`, `registerOption`, and friends. Ember still provides these methods on the owner. They now come from an internal copy of the mixin, so application code and initializers that call `application.register(...)` keep working without changes. +The mixin provided the methods: `register`, `unregister`, `resolveRegistration`, `hasRegistration`, `registerOption`. Ember still provides these methods on the owner. Only using the mixin directly is deprecated. There is no migration for applying the mixin yourself. Remove it. From ea82f2403153bc5f494becbc745fbf94555f3140 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:59:49 -0400 Subject: [PATCH 20/26] Update content/ember/v7/deprecate-observable-mixin.md --- content/ember/v7/deprecate-observable-mixin.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/content/ember/v7/deprecate-observable-mixin.md b/content/ember/v7/deprecate-observable-mixin.md index 8a72d1eb2..b5e7cf027 100644 --- a/content/ember/v7/deprecate-observable-mixin.md +++ b/content/ember/v7/deprecate-observable-mixin.md @@ -74,4 +74,8 @@ Templates and getters that read `count` update automatically because the propert | `addObserver`, `removeObserver` | Derive state with a getter instead of reacting to changes. Where a side effect is required, run it from the method that makes the change. | | `cacheFor` | Not needed. Use `@cached` from `@glimmer/tracking` on a getter when you need memoization. | +As with any usage of the classic, pre-Octane system, there are interop considerations with `tracked`. Follow the [Octane migration guide](https://guides.emberjs.com/v5.7.0/upgrading/current-edition/tracked-properties/) to ensure you migrate in a safe manner. + +At this point, all of `EmberObject` included `computed` is planned to be deprecated under [RFC #1234](https://github.com/emberjs/rfcs/blob/main/text/1234-deprecate-ember-object.md) so fully moving to `tracked` is recommended. + For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116). From 41a79ae2132f17a9b7c9acb11ad46faf6a3fb218 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 12:00:03 -0400 Subject: [PATCH 21/26] Update content/ember/v7/deprecate-registry-proxy-mixin.md Co-authored-by: Katie Gengler --- content/ember/v7/deprecate-registry-proxy-mixin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ember/v7/deprecate-registry-proxy-mixin.md b/content/ember/v7/deprecate-registry-proxy-mixin.md index 58417285c..9d1ceaf59 100644 --- a/content/ember/v7/deprecate-registry-proxy-mixin.md +++ b/content/ember/v7/deprecate-registry-proxy-mixin.md @@ -4,7 +4,7 @@ until: 8.0.0 since: 7.4.0 --- -`RegistryProxyMixin` from `@ember/-internals/runtime` is deprecated. This mixin was private, but importable. +`RegistryProxyMixin` from `@ember/-internals/runtime` is deprecated. This mixin was private but since it may have been used we have added a deprecation as a courtesy through the next LTS. The mixin provided the methods: `register`, `unregister`, `resolveRegistration`, `hasRegistration`, `registerOption`. Ember still provides these methods on the owner. Only using the mixin directly is deprecated. From 0a223ed02921b03f117ab2ba976c8221501b5597 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 12:01:57 -0400 Subject: [PATCH 22/26] Update content/ember/v7/deprecate-registry-proxy-mixin.md Co-authored-by: Katie Gengler --- content/ember/v7/deprecate-registry-proxy-mixin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ember/v7/deprecate-registry-proxy-mixin.md b/content/ember/v7/deprecate-registry-proxy-mixin.md index 9d1ceaf59..7576d4855 100644 --- a/content/ember/v7/deprecate-registry-proxy-mixin.md +++ b/content/ember/v7/deprecate-registry-proxy-mixin.md @@ -1,6 +1,6 @@ --- title: 'RegistryProxyMixin' -until: 8.0.0 +until: 7.9.0 since: 7.4.0 --- From 740426fca0aadb968da834882556efd245b065fa Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 12:02:09 -0400 Subject: [PATCH 23/26] Update content/ember/v7/deprecate-native-array-mixin.md --- content/ember/v7/deprecate-native-array-mixin.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/content/ember/v7/deprecate-native-array-mixin.md b/content/ember/v7/deprecate-native-array-mixin.md index 8aaba97d5..8ce39af9c 100644 --- a/content/ember/v7/deprecate-native-array-mixin.md +++ b/content/ember/v7/deprecate-native-array-mixin.md @@ -38,4 +38,8 @@ If the array never changes after creation, or only changes by reassignment of a Refer to the method tables in the [`EmberArray`](/id/deprecate-ember-array-mixin) and [`MutableArray`](/id/deprecate-mutable-array-mixin) guides for a native equivalent of each method. +As with any usage of the classic, pre-Octane system, there are interop considerations with `tracked`. Follow the [Octane migration guide](https://guides.emberjs.com/v5.7.0/upgrading/current-edition/tracked-properties/) to ensure you migrate in a safe manner. + +At this point, all of `EmberObject` included `computed` is planned to be deprecated under [RFC #1234](https://github.com/emberjs/rfcs/blob/main/text/1234-deprecate-ember-object.md) so fully moving to `tracked` is recommended. + For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116). From 3e3ce591897b9a62ebd253fee1a4eb6fa8e458e6 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 12:02:27 -0400 Subject: [PATCH 24/26] Update content/ember/v7/deprecate-enumerable-mixin.md --- content/ember/v7/deprecate-enumerable-mixin.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/content/ember/v7/deprecate-enumerable-mixin.md b/content/ember/v7/deprecate-enumerable-mixin.md index a8735b2f4..7c11e4735 100644 --- a/content/ember/v7/deprecate-enumerable-mixin.md +++ b/content/ember/v7/deprecate-enumerable-mixin.md @@ -74,4 +74,8 @@ queue.add("b"); The enumerable methods themselves (`firstObject`, `mapBy`, `pushObject`, and friends) live on `EmberArray` and `MutableArray`, which are deprecated as well. Replace them with native equivalents such as `arr[0]`, `map`, and `push`, using `trackedArray` where mutation needs to be tracked. +As with any usage of the classic, pre-Octane system, there are interop considerations with `tracked`. Follow the [Octane migration guide](https://guides.emberjs.com/v5.7.0/upgrading/current-edition/tracked-properties/) to ensure you migrate in a safe manner. + +At this point, all of `EmberObject` included `computed` is planned to be deprecated under [RFC #1234](https://github.com/emberjs/rfcs/blob/main/text/1234-deprecate-ember-object.md) so fully moving to `tracked` is recommended. + For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116). From 01b56465002de54037b377e141988ce8db226935 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 12:02:57 -0400 Subject: [PATCH 25/26] Update content/ember/v7/deprecate-proxy-mixin.md Co-authored-by: Katie Gengler --- content/ember/v7/deprecate-proxy-mixin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ember/v7/deprecate-proxy-mixin.md b/content/ember/v7/deprecate-proxy-mixin.md index 27226e8f9..7f2f35cf8 100644 --- a/content/ember/v7/deprecate-proxy-mixin.md +++ b/content/ember/v7/deprecate-proxy-mixin.md @@ -1,6 +1,6 @@ --- title: 'ProxyMixin' -until: 8.0.0 +until: 7.9.0 since: 7.4.0 --- From 4d27f6ec54322c88f5409e538b4d680647da7deb Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 5 Oct 2026 12:04:30 -0400 Subject: [PATCH 26/26] Apply suggestion from @NullVoxPopuli --- content/ember/v7/deprecate-proxy-mixin.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/content/ember/v7/deprecate-proxy-mixin.md b/content/ember/v7/deprecate-proxy-mixin.md index 7f2f35cf8..e25b2b256 100644 --- a/content/ember/v7/deprecate-proxy-mixin.md +++ b/content/ember/v7/deprecate-proxy-mixin.md @@ -52,4 +52,8 @@ draft.isDraft; // true When the forwarded property set is open-ended, a native `Proxy` covers the same ground. Refer to the [`ObjectProxy` deprecation](/id/deprecate-object-proxy) for that pattern and for `unknownProperty` replacements. +As with any usage of the classic, pre-Octane system, there are interop considerations with `tracked`. Follow the [Octane migration guide](https://guides.emberjs.com/v5.7.0/upgrading/current-edition/tracked-properties/) to ensure you migrate in a safe manner. + +At this point, all of `EmberObject` included `computed` is planned to be deprecated under [RFC #1234](https://github.com/emberjs/rfcs/blob/main/text/1234-deprecate-ember-object.md) so fully moving to `tracked` is recommended. + For more background, read [RFC 1116](https://github.com/emberjs/rfcs/pull/1116).