Deprecations Added in Ember 6.x

What follows is a list of deprecations introduced to Ember during the 6.x cycle.

For more information on deprecations in Ember, see the main deprecations page.

Deprecations Added in 6.3.0

Importing inject from @ember/service

until: 7.0.0
id: importing-inject-from-ember-service

Importing inject from @ember/service is deprecated. Please import service instead.

Example:

my-route.js
import { Route } from '@ember/routing/route';
import { inject as service } from '@ember/service';
import { service } from '@ember/service';

export default class MyRoute extends Route {
  @service store;
}

You can use the ember-codemod-remove-inject-as-service codemod, to fix all violations.

If you're working on a library that needs to support ember-source prior to 4.1, you can support both styles of service via:

import * as emberService from '@ember/service';

const service = emberService.service ?? emberService.inject;

Deprecations Added in 6.5.0

Deprecation of ArrayProxy

until: 7.0.0
id: deprecate-array-proxy

ArrayProxy is deprecated. In modern Ember, you should use tracking primitives—such as tracked arrays and tracked properties—whenever possible. This is almost always the best approach going forward. Some of the examples below demonstrate alternatives using proxies or advanced patterns, but these are generally not ideal. You should strongly consider refactoring your code to use tracking if at all possible, as it leads to simpler, more maintainable, and idiomatic Ember code. However, the best replacement depends on how you were using ArrayProxy. Some example use cases are shown below.

Recommended: Use Tracked Arrays

For most use cases, the modern Ember approach is to use tracked arrays from tracked-built-ins:

import { TrackedArray } from 'tracked-built-ins';

// Instead of ArrayProxy, use TrackedArray directly
const pets = new TrackedArray(['dog', 'cat', 'fish']);

// The array is automatically tracked and will update templates
pets.push('bird');
pets[0]; // 'dog'
pets.length; // 4

This provides automatic tracking without the complexity of proxies and follows modern Ember patterns.

Advanced Use Cases

If you need more advanced behavior like content swapping or transformation, you can use the approaches below. However, these patterns are generally not recommended unless you have a strong reason not to use tracked arrays and properties. In most cases, refactoring to use tracking primitives will result in better, more future-proof code.

Swapping Content

If you were using ArrayProxy to easily swap out the underlying array while keeping a stable reference, you can achieve a similar, transparent effect using a native Proxy backed by a class with a @tracked property. Again, prefer tracked arrays and properties if you can refactor your code to use them.

Before:

import ArrayProxy from '@ember/array/proxy';
import { A } from '@ember/array';

const pets = A(['dog', 'cat', 'fish']);
const proxy = ArrayProxy.create({ content: pets });

proxy.get('firstObject'); // 'dog'

// Later, you can easily swap the content
proxy.set('content', A(['amoeba', 'paramecium']));

proxy.get('firstObject'); // 'amoeba'

After:

import { tracked } from '@glimmer/tracking';

// A helper class to hold the tracked state.
class SwappableState {
  @tracked content;

  constructor(initialContent) {
    this.content = initialContent;
  }
}

// A factory function to create a proxy that is transparent
// and allows swapping the underlying content.
function createSwappableArray(initialContent) {
  const state = new SwappableState(initialContent);

  return new Proxy(state, {
  get(target, property, receiver) {
    // Allow getting/setting the content directly for swapping.
    if (property === 'content') {
      return target.content;
    }
    // Delegate all other property access to the content array.
    return Reflect.get(target.content, property, receiver);
  },
  set(target, property, value, receiver) {
    // Allow setting the content directly for swapping.
    if (property === 'content') {
      target.content = value;
      return true;
    }
    // Delegate all other property sets to the content array.
    return Reflect.set(target.content, property, value, receiver);
  },
  // Add other traps to make the proxy behave like a full array.
  has: (target, key) => key in target.content,
  ownKeys: (target) => Reflect.ownKeys(target.content),
  getOwnPropertyDescriptor: (target, key) => Reflect.getOwnPropertyDescriptor(target.content, key),
  defineProperty: (target, key, desc) => Reflect.defineProperty(target.content, key, desc),
  deleteProperty: (target, key) => Reflect.deleteProperty(target.content, key),
});
}

const pets = createSwappableArray(['dog', 'cat', 'fish']);

// Access the array transparently using native syntax.
pets[0]; // 'dog'
pets.length; // 3

// Later, you can easily swap the content.
// Any part of your app observing this will update because
// the underlying state is tracked.
pets.content = ['amoeba', 'paramecium'];

pets[0]; // 'amoeba'
pets.length; // 2

Transforming Content

If you were using objectAtContent to transform the array's content, you can use a native JavaScript Proxy to achieve the same result with standard array syntax. This is an advanced pattern and should only be used if refactoring to tracked properties is not feasible.

Before:

import ArrayProxy from '@ember/array/proxy';

let pets = ['dog', 'cat', 'fish'];
let proxy = ArrayProxy.create({
  content: pets,
  objectAtContent(idx) {
    return this.get('content').objectAt(idx).toUpperCase();
  }
});

proxy.get('firstObject'); // 'DOG'
proxy.objectAt(1);      // 'CAT'

After:

const pets = ['dog', 'cat', 'fish'];

const transformedPets = new Proxy(pets, {
  get(target, property, receiver) {
    // Check if the property is an array index.
    if (typeof property === 'string' && /^\d+$/.test(property)) {
      const index = parseInt(property, 10);
      const value = target[index];
      return typeof value === 'string' ? value.toUpperCase() : value;
    }

    // For other properties like 'length', delegate to the original array.
    return Reflect.get(target, property, receiver);
  }
});

// Now you can access the transformed items using native array syntax.
transformedPets[0]; // 'DOG'
transformedPets[1]; // 'CAT'

// Other array properties work as expected.
transformedPets.length; // 3

Sorted or Filtered Content (arrangedContent)

If you were using arrangedContent to provide a sorted or filtered view of an array, the modern approach is to use tracked properties and getters:

Before:

import ArrayProxy from '@ember/array/proxy';
import { computed } from '@ember/object';
import { A } from '@ember/array';

const people = A([{name: 'Yehuda'}, {name: 'Tom'}]);

const proxy = ArrayProxy.extend({
  arrangedContent: computed('content.[]', function() {
    // In classic Ember, `sortBy` was a common way to do this.
    return this.get('content').sortBy('name');
  })
}).create({ content: people });

proxy.get('arrangedContent.firstObject.name'); // 'Tom'

// Mutating the content...
people.pushObject({ name: 'Chris' });

// ...is reflected in arrangedContent.
proxy.get('arrangedContent.firstObject.name'); // 'Chris'

After (modern Ember approach with tracked properties):

import { TrackedArray } from 'tracked-built-ins';
import { cached } from '@glimmer/tracking';

class PeopleManager {
  // Use TrackedArray for automatic reactivity
  people = new TrackedArray([{name: 'Yehuda'}, {name: 'Tom'}]);

  @cached
  get arrangedContent() {
    // Automatically recomputes when people array changes
    return [...this.people].sort((a, b) => a.name.localeCompare(b.name));
  }
}

const manager = new PeopleManager();
manager.arrangedContent[0].name; // 'Tom'

// Mutating the content...
manager.people.push({ name: 'Chris' });

// ...is reflected in arrangedContent due to @cached and TrackedArray.
manager.arrangedContent[0].name; // 'Chris'

For more complex use cases where you need a native Proxy for dynamic behavior, you can use the following pattern. However, this is rarely necessary and should be avoided if you can use tracked properties and computed values instead:

// The original data, which can be mutated.
const people = [{name: 'Yehuda'}, {name: 'Tom'}];

// A cache for the sorted version.
let sortedCache = null;
let isDirty = true;

const peopleProxy = new Proxy(people, {
  get(target, property, receiver) {
    // Intercept access to a special 'arranged' property.
    if (property === 'arranged') {
      if (isDirty) {
        // The cache is dirty, so we re-compute the sorted array.
        sortedCache = [...target].sort((a, b) => a.name.localeCompare(b.name));
        isDirty = false;
      }
      return sortedCache;
    }

    // For any other property, delegate to the original array.
    return Reflect.get(target, property, receiver);
  },
  set(target, property, value, receiver) {
    // Any mutation to the array marks the cache as dirty.
    isDirty = true;
    return Reflect.set(target, property, value, receiver);
  }
});

// Access the sorted content via the `arranged` property.
peopleProxy.arranged[0].name; // 'Tom'

// Mutate the original data through the proxy.
peopleProxy.push({ name: 'Chris' });

// The `arranged` property now reflects the change because the cache was invalidated.
peopleProxy.arranged[0].name; // 'Chris'

Migration Strategy

When migrating from ArrayProxy, consider:

  1. First choice (strongly recommended): Use TrackedArray from tracked-built-ins and tracked properties for automatic reactivity and idiomatic Ember code.
  2. For computed arrays: Use @cached getters with tracked data.
  3. Only if truly necessary: Use native Proxy for complex dynamic behavior that cannot be achieved with tracked properties. This should be rare.

The modern Ember approach strongly favors explicit tracking and computed properties over proxy-based solutions. Tracking primitives are easier to understand, debug, and optimize, and will be the best choice for almost all use cases going forward.

Ember.__loader

until: 7.0.0
id: deprecate-import---loader-from-ember

Previously, __loader could be accessed via the Ember import:

import Ember from 'ember';

Ember.__loader

There is no replacement for this API.

Ember._action

until: 7.0.0
id: deprecate-import--action-from-ember

Previously, _action could be accessed via the Ember import:

import Ember from 'ember';

Ember._action

If needed, _action can be imported:

import { action } from '@ember/object';

Ember._array

until: 7.0.0
id: deprecate-import--array-from-ember

Previously, _array could be accessed via the Ember import:

import Ember from 'ember';

Ember._array

If needed, _array can be imported:

import { array } from '@ember/helper';

Ember._assertDestroyablesDestroyed

until: 7.0.0
id: deprecate-import--assert-destroyables-destroyed-from-ember

Previously, _assertDestroyablesDestroyed could be accessed via the Ember import:

import Ember from 'ember';

Ember._assertDestroyablesDestroyed

If needed, _assertDestroyablesDestroyed can be imported:

import { assertDestroyablesDestroyed } from '@ember/destroyable';

Ember._associateDestroyableChild

until: 7.0.0
id: deprecate-import--associate-destroyable-child-from-ember

Previously, _associateDestroyableChild could be accessed via the Ember import:

import Ember from 'ember';

Ember._associateDestroyableChild

If needed, _associateDestroyableChild can be imported:

import { associateDestroyableChild } from '@ember/destroyable';

Ember._Backburner

until: 7.0.0
id: deprecate-import--backburner-from-ember

Previously, _Backburner could be accessed via the Ember import:

import Ember from 'ember';

Ember._Backburner

_Backburner is also private.

There is no replacement for this API.

Ember._Cache

until: 7.0.0
id: deprecate-import--cache-from-ember

Previously, _Cache could be accessed via the Ember import:

import Ember from 'ember';

Ember._Cache

There is no replacement for this API.

Ember._cacheGetValue

until: 7.0.0
id: deprecate-import--cache-get-value-from-ember

Previously, _cacheGetValue could be accessed via the Ember import:

import Ember from 'ember';

Ember._cacheGetValue

If needed, _cacheGetValue can be imported:

import { getValue } from '@glimmer/tracking/primitives/cache';

Ember._cacheIsConst

until: 7.0.0
id: deprecate-import--cache-is-const-from-ember

Previously, _cacheIsConst could be accessed via the Ember import:

import Ember from 'ember';

Ember._cacheIsConst

If needed, _cacheIsConst can be imported:

import { isConst } from '@glimmer/tracking/primitives/cache';

Ember._captureRenderTree

until: 7.0.0
id: deprecate-import--capture-render-tree-from-ember

Previously, _captureRenderTree could be accessed via the Ember import:

import Ember from 'ember';

Ember._captureRenderTree

_captureRenderTree is also private.

If needed, _captureRenderTree can be imported:

import { captureRenderTree } from '@ember/debug';

However, due to _captureRenderTree being private, it is not recommended, nor supported.

Ember._componentManagerCapabilities

until: 7.0.0
id: deprecate-import--component-manager-capabilities-from-ember

Previously, _componentManagerCapabilities could be accessed via the Ember import:

import Ember from 'ember';

Ember._componentManagerCapabilities

If needed, _componentManagerCapabilities can be imported:

import { capabilities } from '@ember/component';

Ember._concat

until: 7.0.0
id: deprecate-import--concat-from-ember

Previously, _concat could be accessed via the Ember import:

import Ember from 'ember';

Ember._concat

If needed, _concat can be imported:

import { concat } from '@ember/helper';

Ember._ContainerProxyMixin

until: 7.0.0
id: deprecate-import--container-proxy-mixin-from-ember

Previously, _ContainerProxyMixin could be accessed via the Ember import:

import Ember from 'ember';

Ember._ContainerProxyMixin

_ContainerProxyMixin is also private.

There is no replacement for this API.

Ember._createCache

until: 7.0.0
id: deprecate-import--create-cache-from-ember

Previously, _createCache could be accessed via the Ember import:

import Ember from 'ember';

Ember._createCache

If needed, _createCache can be imported:

import { createCache } from '@glimmer/tracking/primitives/cache';

Ember._dependentKeyCompat

until: 7.0.0
id: deprecate-import--dependent-key-compat-from-ember

Previously, _dependentKeyCompat could be accessed via the Ember import:

import Ember from 'ember';

Ember._dependentKeyCompat

If needed, _dependentKeyCompat can be imported:

import { dependentKeyCompat } from '@ember/object/compat';

Ember._descriptor

until: 7.0.0
id: deprecate-import--descriptor-from-ember

Previously, _descriptor could be accessed via the Ember import:

import Ember from 'ember';

Ember._descriptor

There is no replacement for this API.

Ember._enableDestroyableTracking

until: 7.0.0
id: deprecate-import--enable-destroyable-tracking-from-ember

Previously, _enableDestroyableTracking could be accessed via the Ember import:

import Ember from 'ember';

Ember._enableDestroyableTracking

If needed, _enableDestroyableTracking can be imported:

import { enableDestroyableTracking } from '@ember/destroyable';

Ember._fn

until: 7.0.0
id: deprecate-import--fn-from-ember

Previously, _fn could be accessed via the Ember import:

import Ember from 'ember';

Ember._fn

If needed, _fn can be imported:

import { fn } from '@ember/helper';

Ember._getComponentTemplate

until: 7.0.0
id: deprecate-import--get-component-template-from-ember

Previously, _getComponentTemplate could be accessed via the Ember import:

import Ember from 'ember';

Ember._getComponentTemplate

If needed, _getComponentTemplate can be imported:

import { getComponentTemplate } from '@ember/component';

Ember._get

until: 7.0.0
id: deprecate-import--get-from-ember

Previously, _get could be accessed via the Ember import:

import Ember from 'ember';

Ember._get

If needed, _get can be imported:

import { get } from '@ember/helper';

Ember._getPath

until: 7.0.0
id: deprecate-import--get-path-from-ember

Previously, _getPath could be accessed via the Ember import:

import Ember from 'ember';

Ember._getPath

There is no replacement for this API.

Ember._hash

until: 7.0.0
id: deprecate-import--hash-from-ember

Previously, _hash could be accessed via the Ember import:

import Ember from 'ember';

Ember._hash

If needed, _hash can be imported:

import { hash } from '@ember/helper';

Ember._helperManagerCapabilities

until: 7.0.0
id: deprecate-import--helper-manager-capabilities-from-ember

Previously, _helperManagerCapabilities could be accessed via the Ember import:

import Ember from 'ember';

Ember._helperManagerCapabilities

If needed, _helperManagerCapabilities can be imported:

import { capabilities } from '@ember/helper';

Ember._Input

until: 7.0.0
id: deprecate-import--input-from-ember

Previously, _Input could be accessed via the Ember import:

import Ember from 'ember';

Ember._Input

If needed, _Input can be imported:

import { Input }  from '@ember/component';

Ember._invokeHelper

until: 7.0.0
id: deprecate-import--invoke-helper-from-ember

Previously, _invokeHelper could be accessed via the Ember import:

import Ember from 'ember';

Ember._invokeHelper

If needed, _invokeHelper can be imported:

import { invokeHelper } from '@ember/helper';

Ember._isDestroyed

until: 7.0.0
id: deprecate-import--is-destroyed-from-ember

Previously, _isDestroyed could be accessed via the Ember import:

import Ember from 'ember';

Ember._isDestroyed

If needed, _isDestroyed can be imported:

import { isDestroyed } from '@ember/destroyable';

Ember._isDestroying

until: 7.0.0
id: deprecate-import--is-destroying-from-ember

Previously, _isDestroying could be accessed via the Ember import:

import Ember from 'ember';

Ember._isDestroying

If needed, _isDestroying can be imported:

import { isDestroying } from '@ember/destroyable';

Ember._modifierManagerCapabilities

until: 7.0.0
id: deprecate-import--modifier-manager-capabilities-from-ember

Previously, _modifierManagerCapabilities could be accessed via the Ember import:

import Ember from 'ember';

Ember._modifierManagerCapabilities

If needed, _modifierManagerCapabilities can be imported:

import { capabilities } from '@ember/modifier';

Ember._on

until: 7.0.0
id: deprecate-import--on-from-ember

Previously, _on could be accessed via the Ember import:

import Ember from 'ember';

Ember._on

If needed, _on can be imported:

import { on } from '@ember/modifier';

Ember._ProxyMixin

until: 7.0.0
id: deprecate-import--proxy-mixin-from-ember

Previously, _ProxyMixin could be accessed via the Ember import:

import Ember from 'ember';

Ember._ProxyMixin

_ProxyMixin is also private.

There is no replacement for this API.

Ember._registerDestructor

until: 7.0.0
id: deprecate-import--register-destructor-from-ember

Previously, _registerDestructor could be accessed via the Ember import:

import Ember from 'ember';

Ember._registerDestructor

If needed, _registerDestructor can be imported:

import { registerDestructor } from '@ember/destroyable';

Ember._RegistryProxyMixin

until: 7.0.0
id: deprecate-import--registry-proxy-mixin-from-ember

Previously, _RegistryProxyMixin could be accessed via the Ember import:

import Ember from 'ember';

Ember._RegistryProxyMixin

_RegistryProxyMixin is also private.

There is no replacement for this API.

Ember._setClassicDecorator

until: 7.0.0
id: deprecate-import--set-classic-decorator-from-ember

Previously, _setClassicDecorator could be accessed via the Ember import:

import Ember from 'ember';

Ember._setClassicDecorator

_setClassicDecorator is also private.

There is no replacement for this API.

Ember._setComponentManager

until: 7.0.0
id: deprecate-import--set-component-manager-from-ember

Previously, _setComponentManager could be accessed via the Ember import:

import Ember from 'ember';

Ember._setComponentManager

If needed, _setComponentManager can be imported:

import { setComponentManager } from '@ember/component';

Ember._setComponentTemplate

until: 7.0.0
id: deprecate-import--set-component-template-from-ember

Previously, _setComponentTemplate could be accessed via the Ember import:

import Ember from 'ember';

Ember._setComponentTemplate

If needed, _setComponentTemplate can be imported:

import { setComponentTemplate } from '@ember/component';

Ember._setHelperManager

until: 7.0.0
id: deprecate-import--set-helper-manager-from-ember

Previously, _setHelperManager could be accessed via the Ember import:

import Ember from 'ember';

Ember._setHelperManager

If needed, _setHelperManager can be imported:

import { setHelperManager } from '@ember/helper';

Ember._setModifierManager

until: 7.0.0
id: deprecate-import--set-modifier-manager-from-ember

Previously, _setModifierManager could be accessed via the Ember import:

import Ember from 'ember';

Ember._setModifierManager

If needed, _setModifierManager can be imported:

import { setModifierManager } from '@ember/modifier';

Ember._templateOnlyComponent

until: 7.0.0
id: deprecate-import--template-only-component-from-ember

Previously, _templateOnlyComponent could be accessed via the Ember import:

import Ember from 'ember';

Ember._templateOnlyComponent

If needed, _templateOnlyComponent can be imported:

import templateOnly from '@ember/component/template-only';

Ember._tracked

until: 7.0.0
id: deprecate-import--tracked-from-ember

Previously, _tracked could be accessed via the Ember import:

import Ember from 'ember';

Ember._tracked

If needed, _tracked can be imported:

import { tracked } from '@glimmer/tracking';

Ember._unregisterDestructor

until: 7.0.0
id: deprecate-import--unregister-destructor-from-ember

Previously, _unregisterDestructor could be accessed via the Ember import:

import Ember from 'ember';

Ember._unregisterDestructor

If needed, _unregisterDestructor can be imported:

import { unregisterDestructor } from '@ember/destroyable';

Ember.A

until: 7.0.0
id: deprecate-import-a-from-ember

Previously, A could be accessed via the Ember import:

import Ember from 'ember';

Ember.A

If needed, A can be imported:

import { A }  from '@ember/array';

Ember.ActionHandler

until: 7.0.0
id: deprecate-import-action-handler-from-ember

Previously, ActionHandler could be accessed via the Ember import:

import Ember from 'ember';

Ember.ActionHandler

ActionHandler is also private.

There is no replacement for this API.

Ember.addListener

until: 7.0.0
id: deprecate-import-add-listener-from-ember

Previously, addListener could be accessed via the Ember import:

import Ember from 'ember';

Ember.addListener

If needed, addListener can be imported:

import { addListener } from '@ember/object/events';

Ember.addObserver

until: 7.0.0
id: deprecate-import-add-observer-from-ember

Previously, addObserver could be accessed via the Ember import:

import Ember from 'ember';

Ember.addObserver

If needed, addObserver can be imported:

import { addObserver } from '@ember/object/observers';

Ember.Application

until: 7.0.0
id: deprecate-import-application-from-ember

Previously, Application could be accessed via the Ember import:

import Ember from 'ember';

Ember.Application

If needed, Application can be imported:

import Application from '@ember/application';

Ember.ApplicationInstance

until: 7.0.0
id: deprecate-import-application-instance-from-ember

Previously, ApplicationInstance could be accessed via the Ember import:

import Ember from 'ember';

Ember.ApplicationInstance

If needed, ApplicationInstance can be imported:

import ApplicationInstance from '@ember/application/instance';

Ember.Array

until: 7.0.0
id: deprecate-import-array-from-ember

Previously, Array could be accessed via the Ember import:

import Ember from 'ember';

Ember.Array

If needed, Array can be imported:

import Array  from '@ember/array';

Ember.ArrayProxy

until: 7.0.0
id: deprecate-import-array-proxy-from-ember

Previously, ArrayProxy could be accessed via the Ember import:

import Ember from 'ember';

Ember.ArrayProxy

If needed, ArrayProxy can be imported:

import ArrayProxy  from '@ember/array/proxy';

Ember.assert

until: 7.0.0
id: deprecate-import-assert-from-ember

Previously, assert could be accessed via the Ember import:

import Ember from 'ember';

Ember.assert

If needed, assert can be imported:

import { assert } from '@ember/debug';

Ember.beginPropertyChanges

until: 7.0.0
id: deprecate-import-begin-property-changes-from-ember

Previously, beginPropertyChanges could be accessed via the Ember import:

import Ember from 'ember';

Ember.beginPropertyChanges

beginPropertyChanges is also private.

There is no replacement for this API.

Ember.BOOTED

until: 7.0.0
id: deprecate-import-booted-from-ember

Previously, BOOTED could be accessed via the Ember import:

import Ember from 'ember';

Ember.BOOTED

BOOTED is also private.

There is no replacement for this API.

Ember.cacheFor

until: 7.0.0
id: deprecate-import-cache-for-from-ember

Previously, cacheFor could be accessed via the Ember import:

import Ember from 'ember';

Ember.cacheFor

There is no replacement for this API.

Ember.canInvoke

until: 7.0.0
id: deprecate-import-can-invoke-from-ember

Previously, canInvoke could be accessed via the Ember import:

import Ember from 'ember';

Ember.canInvoke

canInvoke is also private.

There is no replacement for this API.

Ember.changeProperties

until: 7.0.0
id: deprecate-import-change-properties-from-ember

Previously, changeProperties could be accessed via the Ember import:

import Ember from 'ember';

Ember.changeProperties

changeProperties is also private.

There is no replacement for this API.

Ember.Comparable

until: 7.0.0
id: deprecate-import-comparable-from-ember

Previously, Comparable could be accessed via the Ember import:

import Ember from 'ember';

Ember.Comparable

Comparable is also private.

There is no replacement for this API.

Ember.compare

until: 7.0.0
id: deprecate-import-compare-from-ember

Previously, compare could be accessed via the Ember import:

import Ember from 'ember';

Ember.compare

If needed, compare can be imported:

import { compare } from '@ember/utils';

Ember.Component

until: 7.0.0
id: deprecate-import-component-from-ember

Previously, Component could be accessed via the Ember import:

import Ember from 'ember';

Ember.Component

If needed, Component can be imported:

import Component  from '@ember/component';

Ember.computed

until: 7.0.0
id: deprecate-import-computed-from-ember

Previously, computed could be accessed via the Ember import:

import Ember from 'ember';

Ember.computed

If needed, computed can be imported:

import { computed } from '@ember/object';

Ember.ComputedProperty

until: 7.0.0
id: deprecate-import-computed-property-from-ember

Previously, ComputedProperty could be accessed via the Ember import:

import Ember from 'ember';

Ember.ComputedProperty

There is no replacement for this API.

Ember.ContainerDebugAdapter

until: 7.0.0
id: deprecate-import-container-debug-adapter-from-ember

Previously, ContainerDebugAdapter could be accessed via the Ember import:

import Ember from 'ember';

Ember.ContainerDebugAdapter

If needed, ContainerDebugAdapter can be imported:

import ContainerDebugAdapter from '@ember/debug/container-debug-adapter';

Ember.Container

until: 7.0.0
id: deprecate-import-container-from-ember

Previously, Container could be accessed via the Ember import:

import Ember from 'ember';

Ember.Container

Container is also private.

There is no replacement for this API.

Ember.controllerFor

until: 7.0.0
id: deprecate-import-controller-for-from-ember

Previously, controllerFor could be accessed via the Ember import:

import Ember from 'ember';

Ember.controllerFor

controllerFor is also private.

There is no replacement for this API.

Ember.Controller

until: 7.0.0
id: deprecate-import-controller-from-ember

Previously, Controller could be accessed via the Ember import:

import Ember from 'ember';

Ember.Controller

If needed, Controller can be imported:

import Controller  from '@ember/controller';

Ember.ControllerMixin

until: 7.0.0
id: deprecate-import-controller-mixin-from-ember

Previously, ControllerMixin could be accessed via the Ember import:

import Ember from 'ember';

Ember.ControllerMixin

ControllerMixin is also private.

If needed, ControllerMixin can be imported:

import { ControllerMixin } from '@ember/controller';

However, due to ControllerMixin being private, it is not recommended, nor supported.

Ember.CoreObject

until: 7.0.0
id: deprecate-import-core-object-from-ember

Previously, CoreObject could be accessed via the Ember import:

import Ember from 'ember';

Ember.CoreObject

If needed, CoreObject can be imported:

import EmberObject from '@ember/object';

Ember.DataAdapter

until: 7.0.0
id: deprecate-import-data-adapter-from-ember

Previously, DataAdapter could be accessed via the Ember import:

import Ember from 'ember';

Ember.DataAdapter

If needed, DataAdapter can be imported:

import DataAdapter from '@ember/debug/data-adapter';

Ember.debug

until: 7.0.0
id: deprecate-import-debug-from-ember

Previously, debug could be accessed via the Ember import:

import Ember from 'ember';

Ember.debug

If needed, debug can be imported:

import { debug } from '@ember/debug';

Ember.defineProperty

until: 7.0.0
id: deprecate-import-define-property-from-ember

Previously, defineProperty could be accessed via the Ember import:

import Ember from 'ember';

Ember.defineProperty

If needed, defineProperty can be imported:

import { defineProperty } from '@ember/object';

Ember.deprecate

until: 7.0.0
id: deprecate-import-deprecate-from-ember

Previously, deprecate could be accessed via the Ember import:

import Ember from 'ember';

Ember.deprecate

If needed, deprecate can be imported:

import { deprecate } from '@ember/debug';

Ember.deprecateFunc

until: 7.0.0
id: deprecate-import-deprecate-func-from-ember

Previously, deprecateFunc could be accessed via the Ember import:

import Ember from 'ember';

Ember.deprecateFunc

If needed, deprecateFunc can be imported:

import { deprecateFunc } from '@ember/debug';

Ember.destroy

until: 7.0.0
id: deprecate-import-destroy-from-ember

Previously, destroy could be accessed via the Ember import:

import Ember from 'ember';

Ember.destroy

If needed, destroy can be imported:

import { destroy } from '@ember/destroyable';

Ember.endPropertyChanges

until: 7.0.0
id: deprecate-import-end-property-changes-from-ember

Previously, endPropertyChanges could be accessed via the Ember import:

import Ember from 'ember';

Ember.endPropertyChanges

endPropertyChanges is also private.

There is no replacement for this API.

Ember.Engine

until: 7.0.0
id: deprecate-import-engine-from-ember

Previously, Engine could be accessed via the Ember import:

import Ember from 'ember';

Ember.Engine

If needed, Engine can be imported:

import Engine from '@ember/engine';

Ember.EngineInstance

until: 7.0.0
id: deprecate-import-engine-instance-from-ember

Previously, EngineInstance could be accessed via the Ember import:

import Ember from 'ember';

Ember.EngineInstance

If needed, EngineInstance can be imported:

import Engine from '@ember/engine/instance';

Ember.Enumerable

until: 7.0.0
id: deprecate-import-enumerable-from-ember

Previously, Enumerable could be accessed via the Ember import:

import Ember from 'ember';

Ember.Enumerable

Enumerable is also private.

If needed, Enumerable can be imported:

import Enumerable from '@ember/enumerable';

However, due to Enumerable being private, it is not recommended, nor supported.

Ember.ENV

until: 7.0.0
id: deprecate-import-env-from-ember

Previously, ENV could be accessed via the Ember import:

import Ember from 'ember';

Ember.ENV

If needed, ENV can be imported:

import MyEnv from '<my-app>/config/environment';

For addons, getting access to the environment requires having access to the owner:

import { getOwner } from '@ember/owner';

// ...

let env = getOwner(this).resolveRegistration('config:environment');

Ember.Evented

until: 7.0.0
id: deprecate-import-evented-from-ember

Previously, Evented could be accessed via the Ember import:

import Ember from 'ember';

Ember.Evented

If needed, Evented can be imported:

import Evented from '@ember/object/evented';

Ember.expandProperties

until: 7.0.0
id: deprecate-import-expand-properties-from-ember

Previously, expandProperties could be accessed via the Ember import:

import Ember from 'ember';

Ember.expandProperties

If needed, expandProperties can be imported:

import { expandProperties } from '@ember/object/computed';

Ember.FEATURES

until: 7.0.0
id: deprecate-import-features-from-ember

Previously, FEATURES could be accessed via the Ember import:

import Ember from 'ember';

Ember.FEATURES

If needed, FEATURES can be imported:

import { isEnabled, FEATURES } from '@ember/canary-features';

Ember.generateControllerFactory

until: 7.0.0
id: deprecate-import-generate-controller-factory-from-ember

Previously, generateControllerFactory could be accessed via the Ember import:

import Ember from 'ember';

Ember.generateControllerFactory

generateControllerFactory is also private.

There is no replacement for this API.

Ember.generateController

until: 7.0.0
id: deprecate-import-generate-controller-from-ember

Previously, generateController could be accessed via the Ember import:

import Ember from 'ember';

Ember.generateController

generateController is also private.

There is no replacement for this API.

Ember.generateGuid

until: 7.0.0
id: deprecate-import-generate-guid-from-ember

Previously, generateGuid could be accessed via the Ember import:

import Ember from 'ember';

Ember.generateGuid

generateGuid is also private.

There is no replacement for this API.

Ember.get

until: 7.0.0
id: deprecate-import-get-from-ember

Previously, get could be accessed via the Ember import:

import Ember from 'ember';

Ember.get

If needed, get can be imported:

import { get } from '@ember/object';

Ember.getOwner

until: 7.0.0
id: deprecate-import-get-owner-from-ember

Previously, getOwner could be accessed via the Ember import:

import Ember from 'ember';

Ember.getOwner

If needed, getOwner can be imported:

import { getOwner } from '@ember/owner';

If you're working in a library and need to support earlier than ember-source@4.11, you may use @embroider/macros to selectively import from the old location

import {
  macroCondition,
  dependencySatisfies,
  importSync,
} from '@embroider/macros';

let getOwner;

if (macroCondition(dependencySatisfies('ember-source', '>= 4.11'))) {
  getOwner = importSync('@ember/owner').getOwner;
} else {
  getOwner = importSync('@ember/application').getOwner;
}

Ember.getProperties

until: 7.0.0
id: deprecate-import-get-properties-from-ember

Previously, getProperties could be accessed via the Ember import:

import Ember from 'ember';

Ember.getProperties

If needed, getProperties can be imported:

import { getProperties } from '@ember/object';

Ember.guidFor

until: 7.0.0
id: deprecate-import-guid-for-from-ember

Previously, guidFor could be accessed via the Ember import:

import Ember from 'ember';

Ember.guidFor

If needed, guidFor can be imported:

import { guidFor } from '@ember/object/internals';

Ember.GUID_KEY

until: 7.0.0
id: deprecate-import-guid-key-from-ember

Previously, GUID_KEY could be accessed via the Ember import:

import Ember from 'ember';

Ember.GUID_KEY

GUID_KEY is also private.

There is no replacement for this API.

Ember.Handlebars

until: 7.0.0
id: deprecate-import-handlebars-from-ember

Previously, Handlebars could be accessed via the Ember import:

import Ember from 'ember';

Ember.Handlebars

There is no replacement for this API.

Ember.hasListeners

until: 7.0.0
id: deprecate-import-has-listeners-from-ember

Previously, hasListeners could be accessed via the Ember import:

import Ember from 'ember';

Ember.hasListeners

There is no replacement for this API.

Ember.HashLocation

until: 7.0.0
id: deprecate-import-hash-location-from-ember

Previously, HashLocation could be accessed via the Ember import:

import Ember from 'ember';

Ember.HashLocation

If needed, HashLocation can be imported:

import HashLocation from '@ember/routing/hash-location';

Ember.Helper

until: 7.0.0
id: deprecate-import-helper-from-ember

Previously, Helper could be accessed via the Ember import:

import Ember from 'ember';

Ember.Helper

If needed, Helper can be imported:

import Helper  from '@ember/component/helper';

Ember.HistoryLocation

until: 7.0.0
id: deprecate-import-history-location-from-ember

Previously, HistoryLocation could be accessed via the Ember import:

import Ember from 'ember';

Ember.HistoryLocation

If needed, HistoryLocation can be imported:

import HistoryLocation from '@ember/routing/history-location';

Ember.HTMLBars

until: 7.0.0
id: deprecate-import-htmlbars-from-ember

Previously, HTMLBars could be accessed via the Ember import:

import Ember from 'ember';

Ember.HTMLBars

There is no replacement for this API.

Ember.inject

until: 7.0.0
id: deprecate-import-inject-from-ember

Previously, inject could be accessed via the Ember import:

import Ember from 'ember';

Ember.inject

There is no replacement for this API.

Ember.inspect

until: 7.0.0
id: deprecate-import-inspect-from-ember

Previously, inspect could be accessed via the Ember import:

import Ember from 'ember';

Ember.inspect

inspect is also private.

There is no replacement for this API.

Ember.instrument

until: 7.0.0
id: deprecate-import-instrument-from-ember

Previously, instrument could be accessed via the Ember import:

import Ember from 'ember';

Ember.instrument

instrument is also private.

If needed, instrument can be imported:

import { instrument } from '@ember/instrumentation';

However, due to instrument being private, it is not recommended, nor supported.

Ember.Instrumentation

until: 7.0.0
id: deprecate-import-instrumentation-from-ember

Previously, Instrumentation could be accessed via the Ember import:

import Ember from 'ember';

Ember.Instrumentation

Instrumentation is also private.

If needed, Instrumentation can be imported:

import { * } from '@ember/instrumentation';

However, due to Instrumentation being private, it is not recommended, nor supported.

Ember.isArray

until: 7.0.0
id: deprecate-import-is-array-from-ember

Previously, isArray could be accessed via the Ember import:

import Ember from 'ember';

Ember.isArray

If needed, isArray can be imported:

import { isArray }  from '@ember/array';

Ember.isBlank

until: 7.0.0
id: deprecate-import-is-blank-from-ember

Previously, isBlank could be accessed via the Ember import:

import Ember from 'ember';

Ember.isBlank

If needed, isBlank can be imported:

import { isBlank } from '@ember/utils';

Ember.isEmpty

until: 7.0.0
id: deprecate-import-is-empty-from-ember

Previously, isEmpty could be accessed via the Ember import:

import Ember from 'ember';

Ember.isEmpty

If needed, isEmpty can be imported:

import { isEmpty } from '@ember/utils';

Ember.isEqual

until: 7.0.0
id: deprecate-import-is-equal-from-ember

Previously, isEqual could be accessed via the Ember import:

import Ember from 'ember';

Ember.isEqual

If needed, isEqual can be imported:

import { isEqual } from '@ember/utils';

Ember.isNamespace

until: 7.0.0
id: deprecate-import-is-namespace-from-ember

Previously, isNamespace could be accessed via the Ember import:

import Ember from 'ember';

Ember.isNamespace

There is no replacement for this API.

Ember.isPresent

until: 7.0.0
id: deprecate-import-is-present-from-ember

Previously, isPresent could be accessed via the Ember import:

import Ember from 'ember';

Ember.isPresent

If needed, isPresent can be imported:

import { isPresent } from '@ember/utils';

Ember.libraries

until: 7.0.0
id: deprecate-import-libraries-from-ember

Previously, libraries could be accessed via the Ember import:

import Ember from 'ember';

Ember.libraries

There is no replacement for this API.

If needed, libraries can be imported from a private module:

import { libraries } from '@ember/-internals/metal';

Instead of using this import, consider using a build plugin for your packager. Some options:

  • https://github.com/ubilabs/webpack-node-modules-list
  • https://github.com/yjl9903/unplugin-info

These are both more automatic than Ember's libraries utility.

Ember.lookup

until: 7.0.0
id: deprecate-import-lookup-from-ember

Previously, lookup could be accessed via the Ember import:

import Ember from 'ember';

Ember.lookup

There is no replacement for this API.

Ember.makeArray

until: 7.0.0
id: deprecate-import-make-array-from-ember

Previously, makeArray could be accessed via the Ember import:

import Ember from 'ember';

Ember.makeArray

makeArray is also private.

If needed, makeArray can be imported:

import { makeArray }  from '@ember/array';

However, due to makeArray being private, it is not recommended, nor supported.

Ember.meta

until: 7.0.0
id: deprecate-import-meta-from-ember

Previously, meta could be accessed via the Ember import:

import Ember from 'ember';

Ember.meta

meta is also private.

If needed, meta can be imported:

import { meta } from '@ember/-internals/meta';

However, due to meta being private, it is not recommended, nor supported.

Ember.mixin

until: 7.0.0
id: deprecate-import-mixin-from-ember

Previously, mixin could be accessed via the Ember import:

import Ember from 'ember';

Ember.mixin

mixin is also private.

If needed, mixin can be imported:

import { mixin } from '@ember/object/mixin';

However, due to mixin being private, it is not recommended, nor supported.

Ember.MutableArray

until: 7.0.0
id: deprecate-import-mutable-array-from-ember

Previously, MutableArray could be accessed via the Ember import:

import Ember from 'ember';

Ember.MutableArray

If needed, MutableArray can be imported:

import MutableArray  from '@ember/array/mutable';

Ember.MutableEnumerable

until: 7.0.0
id: deprecate-import-mutable-enumerable-from-ember

Previously, MutableEnumerable could be accessed via the Ember import:

import Ember from 'ember';

Ember.MutableEnumerable

MutableEnumerable is also private.

If needed, MutableEnumerable can be imported:

import MutableEnumerable from '@ember/enumerable/mutable';

However, due to MutableEnumerable being private, it is not recommended, nor supported.

Ember.Namespace

until: 7.0.0
id: deprecate-import-namespace-from-ember

Previously, Namespace could be accessed via the Ember import:

import Ember from 'ember';

Ember.Namespace

If needed, Namespace can be imported:

import Namespace from '@ember/application/namespace';

Ember.NativeArray

until: 7.0.0
id: deprecate-import-native-array-from-ember

Previously, NativeArray could be accessed via the Ember import:

import Ember from 'ember';

Ember.NativeArray

If needed, NativeArray can be imported:

import { NativeArray }  from '@ember/array';

Ember.NoneLocation

until: 7.0.0
id: deprecate-import-none-location-from-ember

Previously, NoneLocation could be accessed via the Ember import:

import Ember from 'ember';

Ember.NoneLocation

If needed, NoneLocation can be imported:

import NoneLocation from '@ember/routing/none-location';

Ember.notifyPropertyChange

until: 7.0.0
id: deprecate-import-notify-property-change-from-ember

Previously, notifyPropertyChange could be accessed via the Ember import:

import Ember from 'ember';

Ember.notifyPropertyChange

If needed, notifyPropertyChange can be imported:

import { notifyPropertyChange } from '@ember/object';

Ember.Object

until: 7.0.0
id: deprecate-import-object-from-ember

Previously, Object could be accessed via the Ember import:

import Ember from 'ember';

Ember.Object

If needed, Object can be imported:

import Object from '@ember/object';

Ember.ObjectProxy

until: 7.0.0
id: deprecate-import-object-proxy-from-ember

Previously, ObjectProxy could be accessed via the Ember import:

import Ember from 'ember';

Ember.ObjectProxy

If needed, ObjectProxy can be imported:

import ObjectProxy from '@ember/object/proxy';

Ember.Observable

until: 7.0.0
id: deprecate-import-observable-from-ember

Previously, Observable could be accessed via the Ember import:

import Ember from 'ember';

Ember.Observable

If needed, Observable can be imported:

import Observable from '@ember/object/observable';

Ember.observer

until: 7.0.0
id: deprecate-import-observer-from-ember

Previously, observer could be accessed via the Ember import:

import Ember from 'ember';

Ember.observer

If needed, observer can be imported:

import { observer } from '@ember/object';

Ember.on

until: 7.0.0
id: deprecate-import-on-from-ember

Previously, on could be accessed via the Ember import:

import Ember from 'ember';

Ember.on

If needed, on can be imported:

import { on } from '@ember/object/evented';

Ember.onLoad

until: 7.0.0
id: deprecate-import-on-load-from-ember

Previously, onLoad could be accessed via the Ember import:

import Ember from 'ember';

Ember.onLoad

If needed, onLoad can be imported:

import { onLoad } from '@ember/application';

Ember.onerror

until: 7.0.0
id: deprecate-import-onerror-from-ember

Previously, onerror could be accessed via the Ember import:

import Ember from 'ember';

Ember.onerror

There is no replacement for this API.

Ember.PromiseProxyMixin

until: 7.0.0
id: deprecate-import-promise-proxy-mixin-from-ember

Previously, PromiseProxyMixin could be accessed via the Ember import:

import Ember from 'ember';

Ember.PromiseProxyMixin

If needed, PromiseProxyMixin can be imported:

import EmberPromiseProxyMixin from '@ember/object/promise-proxy-mixin';

Ember.Registry

until: 7.0.0
id: deprecate-import-registry-from-ember

Previously, Registry could be accessed via the Ember import:

import Ember from 'ember';

Ember.Registry

Registry is also private.

There is no replacement for this API.

Ember.removeListener

until: 7.0.0
id: deprecate-import-remove-listener-from-ember

Previously, removeListener could be accessed via the Ember import:

import Ember from 'ember';

Ember.removeListener

If needed, removeListener can be imported:

import { removeListener } from '@ember/object/events';

Ember.removeObserver

until: 7.0.0
id: deprecate-import-remove-observer-from-ember

Previously, removeObserver could be accessed via the Ember import:

import Ember from 'ember';

Ember.removeObserver

If needed, removeObserver can be imported:

import { removeObserver } from '@ember/object/observers';

Ember.Route

until: 7.0.0
id: deprecate-import-route-from-ember

Previously, Route could be accessed via the Ember import:

import Ember from 'ember';

Ember.Route

If needed, Route can be imported:

import Route from '@ember/routing/route';

Ember.RouterDSL

until: 7.0.0
id: deprecate-import-router-dsl-from-ember

Previously, RouterDSL could be accessed via the Ember import:

import Ember from 'ember';

Ember.RouterDSL

There is no replacement for this API.

Ember.RSVP

until: 7.0.0
id: deprecate-import-rsvp-from-ember

Previously, RSVP could be accessed via the Ember import:

import Ember from 'ember';

Ember.RSVP

If needed, RSVP can be imported:

import RSVP from 'rsvp';

Ember.run

until: 7.0.0
id: deprecate-import-run-from-ember

Previously, run could be accessed via the Ember import:

import Ember from 'ember';

Ember.run

If needed, run can be imported:

import { run } from '@ember/runloop';

Ember.runInDebug

until: 7.0.0
id: deprecate-import-run-in-debug-from-ember

Previously, runInDebug could be accessed via the Ember import:

import Ember from 'ember';

Ember.runInDebug

If needed, runInDebug can be imported:

import { runInDebug } from '@ember/debug';

Ember.runLoadHooks

until: 7.0.0
id: deprecate-import-run-load-hooks-from-ember

Previously, runLoadHooks could be accessed via the Ember import:

import Ember from 'ember';

Ember.runLoadHooks

If needed, runLoadHooks can be imported:

import { runLoadHooks } from '@ember/application';

Ember.sendEvent

until: 7.0.0
id: deprecate-import-send-event-from-ember

Previously, sendEvent could be accessed via the Ember import:

import Ember from 'ember';

Ember.sendEvent

If needed, sendEvent can be imported:

import { sendEvent } from '@ember/object/events';

Ember.Service

until: 7.0.0
id: deprecate-import-service-from-ember

Previously, Service could be accessed via the Ember import:

import Ember from 'ember';

Ember.Service

If needed, Service can be imported:

import Service from '@ember/service';

Ember.set

until: 7.0.0
id: deprecate-import-set-from-ember

Previously, set could be accessed via the Ember import:

import Ember from 'ember';

Ember.set

If needed, set can be imported:

import { set } from '@ember/object';

Ember.setOwner

until: 7.0.0
id: deprecate-import-set-owner-from-ember

Previously, setOwner could be accessed via the Ember import:

import Ember from 'ember';

Ember.setOwner

If needed, setOwner can be imported:

import { setOwner } from '@ember/owner';

If you're working in a library and need to support earlier than ember-source@4.11, you may use @embroider/macros to selectively import from the old location

import {
  macroCondition,
  dependencySatisfies,
  importSync,
} from '@embroider/macros';

let setOwner;

if (macroCondition(dependencySatisfies('ember-source', '>= 4.11'))) {
  setOwner = importSync('@ember/owner').setOwner;
} else {
  setOwner = importSync('@ember/application').setOwner;
}

Ember.setProperties

until: 7.0.0
id: deprecate-import-set-properties-from-ember

Previously, setProperties could be accessed via the Ember import:

import Ember from 'ember';

Ember.setProperties

If needed, setProperties can be imported:

import { setProperties } from '@ember/object';

Ember.setupForTesting

until: 7.0.0
id: deprecate-import-setup-for-testing-from-ember

Previously, setupForTesting could be accessed via the Ember import:

import Ember from 'ember';

Ember.setupForTesting

There is no replacement for this API.

Ember.subscribe

until: 7.0.0
id: deprecate-import-subscribe-from-ember

Previously, subscribe could be accessed via the Ember import:

import Ember from 'ember';

Ember.subscribe

subscribe is also private.

If needed, subscribe can be imported:

import { subscribe } from '@ember/instrumentation';

However, due to subscribe being private, it is not recommended, nor supported.

Ember.TEMPLATES

until: 7.0.0
id: deprecate-import-templates-from-ember

Previously, TEMPLATES could be accessed via the Ember import:

import Ember from 'ember';

Ember.TEMPLATES

TEMPLATES is also private.

There is no replacement for this API.

Ember.Test

until: 7.0.0
id: deprecate-import-test-from-ember

Previously, Test could be accessed via the Ember import:

import Ember from 'ember';

Ember.Test

There is no replacement for this API.

Ember.testing

until: 7.0.0
id: deprecate-import-testing-from-ember

Previously, testing could be accessed via the Ember import:

import Ember from 'ember';

Ember.testing

There is no replacement for this API.

Ember.toString

until: 7.0.0
id: deprecate-import-to-string-from-ember

Previously, toString could be accessed via the Ember import:

import Ember from 'ember';

Ember.toString

There is no replacement for this API.

Ember.trySet

until: 7.0.0
id: deprecate-import-try-set-from-ember

Previously, trySet could be accessed via the Ember import:

import Ember from 'ember';

Ember.trySet

If needed, trySet can be imported:

import { trySet } from '@ember/object';

Ember.typeOf

until: 7.0.0
id: deprecate-import-type-of-from-ember

Previously, typeOf could be accessed via the Ember import:

import Ember from 'ember';

Ember.typeOf

If needed, typeOf can be imported:

import { typeOf } from '@ember/utils';

Ember.uuid

until: 7.0.0
id: deprecate-import-uuid-from-ember

Previously, uuid could be accessed via the Ember import:

import Ember from 'ember';

Ember.uuid

There is no replacement for this API.

Ember.VERSION

until: 7.0.0
id: deprecate-import-version-from-ember

Previously, VERSION could be accessed via the Ember import:

import Ember from 'ember';

Ember.VERSION

If needed, VERSION can be imported:

import { VERSION } from '@ember/version';

Ember.ViewUtils

until: 7.0.0
id: deprecate-import-view-utils-from-ember

Previously, ViewUtils could be accessed via the Ember import:

import Ember from 'ember';

Ember.ViewUtils

ViewUtils is also private.

If needed, ViewUtils can be imported:

import { isSerializationFirstNode } from '@ember/-internals/glimmer';

However, due to ViewUtils being private, it is not recommended, nor supported.

Ember.warn

until: 7.0.0
id: deprecate-import-warn-from-ember

Previously, warn could be accessed via the Ember import:

import Ember from 'ember';

Ember.warn

If needed, warn can be imported:

import { warn } from '@ember/debug';

Ember.wrap

until: 7.0.0
id: deprecate-import-wrap-from-ember

Previously, wrap could be accessed via the Ember import:

import Ember from 'ember';

Ember.wrap

wrap is also private.

There is no replacement for this API.

Deprecation of ObjectProxy

until: 7.0.0
id: deprecate-object-proxy

ObjectProxy is deprecated. In modern Ember, you should use tracked properties and native JavaScript patterns instead. The best replacement depends on how you were using ObjectProxy. Some example use cases are shown below.

Recommended: Use Tracked Properties

For most use cases, the modern Ember approach is to use tracked properties directly:

import { tracked } from '@glimmer/tracking';

class PersonManager {
  @tracked person = { name: 'Tom' };

  // Easy to swap content and templates will update automatically
  updatePerson(newPerson) {
    this.person = newPerson;
  }
}

This provides automatic tracking without the complexity of proxies and follows modern Ember patterns.

Advanced Use Cases

If you need more advanced behavior like content swapping with a stable reference or property interception, you can use the approaches below.

Swapping Content

If you were using ObjectProxy to easily swap out the underlying object while keeping a stable reference, you can achieve a similar, transparent effect using a native Proxy backed by a class with a @tracked property.

Before:

import ObjectProxy from '@ember/object/proxy';

const person = { name: 'Tom' };
const proxy = ObjectProxy.create({ content: person });

proxy.get('name'); // 'Tom'

// Later, you can easily swap the content
proxy.set('content', { name: 'Thomas' });

proxy.get('name'); // 'Thomas'

After:

import { tracked } from '@glimmer/tracking';

// A helper class to hold the tracked state.
class SwappableState {
  @tracked content;

  constructor(initialContent) {
    this.content = initialContent;
  }
}

// A factory function to create a proxy that is transparent
// and allows swapping the underlying content.
function createSwappableObject(initialContent) {
  const state = new SwappableState(initialContent);

  return new Proxy(state, {
    get(target, property, receiver) {
      // Allow getting/setting the content directly for swapping.
      if (property === 'content') {
        return target.content;
      }
      // Delegate all other property access to the content object.
      return Reflect.get(target.content, property, receiver);
    },
    set(target, property, value, receiver) {
      // Allow setting the content directly for swapping.
      if (property === 'content') {
        target.content = value;
        return true;
      }
      // Delegate all other property sets to the content object.
      return Reflect.set(target.content, property, value, receiver);
    },
    // Add other traps to make the proxy behave like a full object.
    has: (target, key) => key in target.content,
    ownKeys: (target) => Reflect.ownKeys(target.content),
    getOwnPropertyDescriptor: (target, key) => Reflect.getOwnPropertyDescriptor(target.content, key),
    defineProperty: (target, key, desc) => Reflect.defineProperty(target.content, key, desc),
    deleteProperty: (target, key) => Reflect.deleteProperty(target.content, key),
  });
}

const person = createSwappableObject({ name: 'Tom' });

// Access properties transparently.
person.name; // 'Tom'

// Later, you can easily swap the content.
// Any part of your app observing this will update because
// the underlying state is tracked.
person.content = { name: 'Thomas' };

person.name; // 'Thomas'

Adding/Overriding Properties

If you had computed properties on your proxy or were using it to add or override behavior, you often don't need a proxy at all. You can simply add a getter to the object:

Before:

import ObjectProxy from '@ember/object/proxy';
import { computed } from '@ember/object';

const ProxyWithComputedProperty = ObjectProxy.extend({
  fullName: computed('firstName', 'lastName', function() {
    return `${this.get('firstName')} ${this.get('lastName')}`;
  })
});

let proxy = ProxyWithComputedProperty.create({
  content: { firstName: 'Tom', lastName: 'Dale' }
});

proxy.get('fullName'); // 'Tom Dale'

After:

const person = {
  firstName: 'Tom',
  lastName: 'Dale',
  get fullName() {
    // or person.firstName person.lastName
    return `${this.firstName} ${this.lastName}`;
  }
};

person.fullName; // 'Tom Dale'
person.firstName; // 'Tom'

If you need to add properties to an object you can't modify, you can use a native Proxy:

const person = { firstName: 'Tom', lastName: 'Dale' };

const personProxy = new Proxy(person, {
  get(target, property, receiver) {
    if (property === 'fullName') {
      return `${target.firstName} ${target.lastName}`;
    }
    return Reflect.get(target, property, receiver);
  }
});

personProxy.fullName; // 'Tom Dale'
personProxy.firstName; // 'Tom'

Handling Unknown Properties (unknownProperty)

For more advanced use cases, ObjectProxy provided an unknownProperty hook to handle access to properties that don't exist. The get trap in a native Proxy provides the same capability.

Before:

import ObjectProxy from '@ember/object/proxy';

const proxy = ObjectProxy.extend({
  unknownProperty(key) {
    return `Property '${key}' does not exist.`;
  }
}).create({
  content: { a: 1 }
});

proxy.get('a'); // 1
proxy.get('b'); // "Property 'b' does not exist."

After:

const data = { a: 1 };

const handler = {
  get(target, key, receiver) {
    if (key in target) {
      return Reflect.get(target, key, receiver);
    }
    return `Property '${key}' does not exist.`;
  }
};

const proxy = new Proxy(data, handler);

proxy.a; // 1
proxy.b; // "Property 'b' does not exist."

Migration Strategy

When migrating from ObjectProxy, consider:

  1. First choice: Use @tracked properties and direct object access
  2. For computed properties: Add getters directly to objects when possible
  3. Only if needed: Use native Proxy for dynamic property access or when you can't modify the original object

The modern Ember approach favors explicit tracked properties and direct object access over proxy-based solutions, which are easier to understand, debug, and have better performance characteristics.

Deprecation of PromiseProxyMixin

until: 7.0.0
id: deprecate-promise-proxy-mixin

PromiseProxyMixin is deprecated. You should use native async/await and Promises directly to manage asynchronous operations and their state.

PromiseProxyMixin was used to create proxy objects that represented the eventual result of a promise, with properties to track the promise's lifecycle (isPending, isFulfilled, etc.).

Replacing PromiseProxyMixin

The modern approach is to use a class (like a component or service) to manage the state of the asynchronous operation.

Before:

import ObjectProxy from '@ember/object/proxy';
import PromiseProxyMixin from '@ember/object/promise-proxy-mixin';

const PromiseObject = ObjectProxy.extend(PromiseProxyMixin);

const promise = new Promise(resolve => resolve({ value: 42 }));
const proxy = PromiseObject.create({ promise });

// In a template, you might have:
// {{#if proxy.isPending}}
//   Loading...
// {{else if proxy.isFulfilled}}
//   Value: {{proxy.content.value}}
// {{else if proxy.isRejected}}
//   Error: {{proxy.reason}}
// {{/if}}

After (using async/await and tracked properties in a component):

import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { task } from 'ember-concurrency';

export default class MyComponent extends Component {
  @task
  *loadData() {
    try {
      const promise = new Promise(resolve => resolve({ value: 42 }));
      const content = yield promise;
      return content;
    } catch (e) {
      // ember-concurrency provides its own error state
      throw e;
    }
  }

  get lastTask() {
    return this.loadData.last;
  }

  <template>
    {{#if this.lastTask.isRunning}}
      Loading...
    {{else if this.lastTask.isSuccessful}}
      Value: {{this.lastTask.value}}
    {{else if this.lastTask.error}}
      Error: {{this.lastTask.error}}
    {{/if}}
  </template>
}

For simpler cases where you don't need the full power of a library like ember-concurrency, you can manage the state manually with @tracked properties:

import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';

export default class MyComponent extends Component {
  @tracked isLoading = true;
  @tracked error = null;
  @tracked content = null;

  constructor() {
    super(...arguments);
    this.loadData();
  }

  async loadData() {
    try {
      this.isLoading = true;
      const promise = new Promise(resolve => resolve({ value: 42 }));
      this.content = await promise;
    } catch (e) {
      this.error = e;
    } finally {
      this.isLoading = false;
    }
  }

  <template>
    {{#if this.isLoading}}
      Loading...
    {{else if this.content}}
      Value: {{this.content.value}}
    {{else if this.error}}
      Error: {{this.error}}
    {{/if}}
  </template>
}

Using a library like ember-concurrency is highly recommended for managing concurrent asynchronous user-initiated tasks in Ember applications, as it provides robust solutions for handling loading/error states, cancellation, and more.

For data loading specifically, you may also want to consider using WarpDrive (formerly Ember Data) which provides a number of utilities around tracking for data.

Migration Strategy

When migrating from PromiseProxyMixin, consider:

  1. First choice: Use ember-concurrency for user-initiated async tasks (button clicks, form submissions)
  2. For data loading: Consider getRequestState from warp-drive for request state management
  3. For simple cases: Use @tracked properties with async/await and manual state management

The modern Ember approach uses explicit async/await patterns and proper state management libraries rather than proxy-based promise wrappers.