From cfad78f1b0bab14d460c8ea28cd688461afac553 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Sun, 25 Jul 2021 12:23:40 -0500 Subject: [PATCH] [CLEANUP beta] Deprecate owner.inject, drop implicit injections --- .../files/__root__/initializers/__name__.js | 1 - .../instance-initializers/__name__.js | 1 - .../initializer/initializer-nested.js | 1 - .../fixtures/initializer/initializer.js | 1 - .../instance-initializer-nested.js | 1 - .../instance-initializer.js | 1 - .../-internals/container/lib/container.ts | 77 +---- .../-internals/container/lib/registry.ts | 167 +--------- .../container/tests/container_test.js | 194 +---------- .../container/tests/registry_test.js | 92 ------ .../lib/container_debug_adapter.js | 7 + .../@ember/-internals/glimmer/lib/renderer.ts | 21 +- .../-internals/glimmer/lib/setup-registry.ts | 14 +- .../-internals/glimmer/lib/views/outlet.ts | 7 +- .../glimmer/tests/integration/outlet-test.js | 5 +- .../-internals/routing/lib/system/router.ts | 5 +- .../routing/tests/system/route_test.js | 32 -- .../runtime/lib/system/core_object.js | 127 +------- .../tests/system/object/create_test.js | 303 +----------------- .../@ember/application/lib/application.js | 11 +- .../application/tests/application_test.js | 10 - .../tests/dependency_injection_test.js | 18 -- packages/@ember/engine/index.js | 6 - packages/@ember/engine/instance.js | 5 - packages/@ember/engine/tests/engine_test.js | 11 - .../ember/tests/ember-test-helpers-test.js | 4 +- packages/internal-test-helpers/index.js | 2 +- .../lib/registry-check.js | 25 -- .../lib/test-cases/rendering.js | 4 +- .../lib/test-cases/router-non-application.js | 4 +- tests/docs/expected.js | 4 - tests/node/helpers/setup-component.js | 3 +- tests/node/visit-test.js | 59 ++-- 33 files changed, 110 insertions(+), 1113 deletions(-) diff --git a/blueprints/initializer/files/__root__/initializers/__name__.js b/blueprints/initializer/files/__root__/initializers/__name__.js index dfb969b2702..f3083e3831a 100644 --- a/blueprints/initializer/files/__root__/initializers/__name__.js +++ b/blueprints/initializer/files/__root__/initializers/__name__.js @@ -1,5 +1,4 @@ export function initialize(/* application */) { - // application.inject('route', 'foo', 'service:foo'); } export default { diff --git a/blueprints/instance-initializer/files/__root__/instance-initializers/__name__.js b/blueprints/instance-initializer/files/__root__/instance-initializers/__name__.js index 2f84dce8d92..fefc0f80a2d 100644 --- a/blueprints/instance-initializer/files/__root__/instance-initializers/__name__.js +++ b/blueprints/instance-initializer/files/__root__/instance-initializers/__name__.js @@ -1,5 +1,4 @@ export function initialize(/* appInstance */) { - // appInstance.inject('route', 'foo', 'service:foo'); } export default { diff --git a/node-tests/fixtures/initializer/initializer-nested.js b/node-tests/fixtures/initializer/initializer-nested.js index dfb969b2702..f3083e3831a 100644 --- a/node-tests/fixtures/initializer/initializer-nested.js +++ b/node-tests/fixtures/initializer/initializer-nested.js @@ -1,5 +1,4 @@ export function initialize(/* application */) { - // application.inject('route', 'foo', 'service:foo'); } export default { diff --git a/node-tests/fixtures/initializer/initializer.js b/node-tests/fixtures/initializer/initializer.js index dfb969b2702..f3083e3831a 100644 --- a/node-tests/fixtures/initializer/initializer.js +++ b/node-tests/fixtures/initializer/initializer.js @@ -1,5 +1,4 @@ export function initialize(/* application */) { - // application.inject('route', 'foo', 'service:foo'); } export default { diff --git a/node-tests/fixtures/instance-initializer/instance-initializer-nested.js b/node-tests/fixtures/instance-initializer/instance-initializer-nested.js index 2f84dce8d92..fefc0f80a2d 100644 --- a/node-tests/fixtures/instance-initializer/instance-initializer-nested.js +++ b/node-tests/fixtures/instance-initializer/instance-initializer-nested.js @@ -1,5 +1,4 @@ export function initialize(/* appInstance */) { - // appInstance.inject('route', 'foo', 'service:foo'); } export default { diff --git a/node-tests/fixtures/instance-initializer/instance-initializer.js b/node-tests/fixtures/instance-initializer/instance-initializer.js index 2f84dce8d92..fefc0f80a2d 100644 --- a/node-tests/fixtures/instance-initializer/instance-initializer.js +++ b/node-tests/fixtures/instance-initializer/instance-initializer.js @@ -1,5 +1,4 @@ export function initialize(/* appInstance */) { - // appInstance.inject('route', 'foo', 'service:foo'); } export default { diff --git a/packages/@ember/-internals/container/lib/container.ts b/packages/@ember/-internals/container/lib/container.ts index 2f52ae92c25..d811fd971c1 100644 --- a/packages/@ember/-internals/container/lib/container.ts +++ b/packages/@ember/-internals/container/lib/container.ts @@ -2,7 +2,7 @@ import { Factory, LookupOptions, Owner, setOwner } from '@ember/-internals/owner import { dictionary, symbol } from '@ember/-internals/utils'; import { assert } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; -import Registry, { DebugRegistry, Injection } from './registry'; +import Registry, { DebugRegistry } from './registry'; declare global { export function gc(): void; @@ -406,68 +406,6 @@ function instantiateFactory( throw new Error('Could not create factory'); } -interface BuildInjectionsResult { - injections: { [key: string]: unknown }; - isDynamic: boolean; -} - -function processInjections( - container: Container, - injections: Injection[], - result: BuildInjectionsResult -) { - if (DEBUG) { - container.registry.validateInjections(injections); - } - - let hash = result.injections; - - for (let i = 0; i < injections.length; i++) { - let { property, specifier } = injections[i]; - - hash[property] = lookup(container, specifier); - - if (!result.isDynamic) { - result.isDynamic = !isSingleton(container, specifier); - } - } -} - -function buildInjections( - container: Container, - typeInjections: Injection[], - injections: Injection[] -): BuildInjectionsResult { - let injectionsHash = {}; - - setOwner(injectionsHash, container.owner!); - - let result: BuildInjectionsResult = { - injections: injectionsHash, - isDynamic: false, - }; - - if (typeInjections !== undefined) { - processInjections(container, typeInjections, result); - } - - if (injections !== undefined) { - processInjections(container, injections, result); - } - - return result; -} - -function injectionsFor(container: Container, fullName: string) { - let registry = container.registry; - let [type] = fullName.split(':'); - - let typeInjections = registry.getTypeInjections(type); - let injections = registry.getInjections(fullName); - - return buildInjections(container, typeInjections, injections); -} - function destroyDestroyables(container: Container): void { let cache = container.cache; let keys = Object.keys(cache); @@ -569,16 +507,9 @@ class FactoryManager { ); } - let props = this.injections; - if (props === undefined) { - let { injections, isDynamic } = injectionsFor(this.container, this.normalizedName); - setFactoryFor(injections, this); - props = injections; - - if (!isDynamic) { - this.injections = injections; - } - } + let props = {}; + setOwner(props, container.owner!); + setFactoryFor(props, this); if (options !== undefined) { props = Object.assign({}, props, options); diff --git a/packages/@ember/-internals/container/lib/registry.ts b/packages/@ember/-internals/container/lib/registry.ts index 6d8634d8537..d89e24b15e3 100644 --- a/packages/@ember/-internals/container/lib/registry.ts +++ b/packages/@ember/-internals/container/lib/registry.ts @@ -1,6 +1,6 @@ import { Factory } from '@ember/-internals/owner'; import { dictionary, intern } from '@ember/-internals/utils'; -import { assert } from '@ember/debug'; +import { assert, deprecate } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; import Container, { ContainerOptions, LazyInjection } from './container'; @@ -24,14 +24,12 @@ export interface KnownForTypeResult { export interface IRegistry { describe(fullName: string): string; - getInjections(fullName: string): Injection[]; getOption( fullName: string, optionName: K ): TypeOptions[K] | undefined; getOptions(fullName: string): TypeOptions; getOptionsForType(type: string): TypeOptions; - getTypeInjections(type: string): Injection[]; knownForType(type: string): KnownForTypeResult; makeToString(factory: Factory, fullName: string): string; normalizeFullName(fullName: string): string; @@ -82,12 +80,10 @@ export default class Registry implements IRegistry { resolver: Resolver | (Resolve & NotResolver) | null; readonly fallback: IRegistry | null; readonly registrations: { [key: string]: object }; - readonly _injections: { [key: string]: Injection[] }; _localLookupCache: { [key: string]: object }; readonly _normalizeCache: { [key: string]: string }; readonly _options: { [key: string]: TypeOptions }; readonly _resolveCache: { [key: string]: object }; - readonly _typeInjections: { [key: string]: Injection[] }; readonly _typeOptions: { [key: string]: TypeOptions }; constructor(options: RegistryOptions = {}) { @@ -96,9 +92,6 @@ export default class Registry implements IRegistry { this.registrations = dictionary(options.registrations || null); - this._typeInjections = dictionary(null); - this._injections = dictionary(null); - this._localLookupCache = Object.create(null); this._normalizeCache = dictionary(null); this._resolveCache = dictionary(null); @@ -130,20 +123,6 @@ export default class Registry implements IRegistry { @type InheritingDict */ - /** - @private - - @property _typeInjections - @type InheritingDict - */ - - /** - @private - - @property _injections - @type InheritingDict - */ - /** @private @@ -468,90 +447,9 @@ export default class Registry implements IRegistry { } /** - Used only via `injection`. - - Provides a specialized form of injection, specifically enabling - all objects of one type to be injected with a reference to another - object. - - For example, provided each object of type `controller` needed a `router`. - one would do the following: - - ```javascript - let registry = new Registry(); - let container = registry.container(); - - registry.register('router:main', Router); - registry.register('controller:user', UserController); - registry.register('controller:post', PostController); - - registry.typeInjection('controller', 'router', 'router:main'); - - let user = container.lookup('controller:user'); - let post = container.lookup('controller:post'); - - user.router instanceof Router; //=> true - post.router instanceof Router; //=> true - - // both controllers share the same router - user.router === post.router; //=> true - ``` - - @private - @method typeInjection - @param {String} type - @param {String} property - @param {String} fullName - */ - typeInjection(type: string, property: string, fullName: string): void { - assert('fullName must be a proper full name', this.isValidFullName(fullName)); - - let fullNameType = fullName.split(':')[0]; - assert(`Cannot inject a '${fullName}' on other ${type}(s).`, fullNameType !== type); - - let injections = this._typeInjections[type] || (this._typeInjections[type] = []); - - injections.push({ property, specifier: fullName }); - } - - /** - Defines injection rules. - - These rules are used to inject dependencies onto objects when they - are instantiated. - - Two forms of injections are possible: + This is deprecated in favor of explicit injection of dependencies. - * Injecting one fullName on another fullName - * Injecting one fullName on a type - - Example: - - ```javascript - let registry = new Registry(); - let container = registry.container(); - - registry.register('source:main', Source); - registry.register('model:user', User); - registry.register('model:post', Post); - - // injecting one fullName on another fullName - // eg. each user model gets a post model - registry.injection('model:user', 'post', 'model:post'); - - // injecting one fullName on another type - registry.injection('model', 'source', 'source:main'); - - let user = container.lookup('model:user'); - let post = container.lookup('model:post'); - - user.source instanceof Source; //=> true - post.source instanceof Source; //=> true - - user.post instanceof Post; //=> true - - // and both models share the same source - user.source === post.source; //=> true + Reference: https://deprecations.emberjs.com/v3.x#toc_implicit-injections ``` @private @@ -559,25 +457,22 @@ export default class Registry implements IRegistry { @param {String} factoryName @param {String} property @param {String} injectionName + @deprecated */ - injection(fullName: string, property: string, injectionName: string) { - assert( - `Invalid injectionName, expected: 'type:name' got: ${injectionName}`, - this.isValidFullName(injectionName) + injection(fullName: string, property: string) { + deprecate( + `As of Ember 4.0.0, owner.inject no longer injects values into resolved instances, and calling the method has been deprecated. Since this method no longer does anything, it is fully safe to remove this injection. As an alternative to this API, you can refactor to explicitly inject \`${property}\` on \`${fullName}\`, or look it up directly using the \`getOwner\` API.`, + false, + { + id: 'remove-owner-inject', + until: '5.0.0', + url: 'https://deprecations.emberjs.com/v4.x#toc_implicit-injections', + for: 'ember-source', + since: { + enabled: '4.0.0', + }, + } ); - - let normalizedInjectionName = this.normalize(injectionName); - - if (fullName.indexOf(':') === -1) { - return this.typeInjection(fullName, property, normalizedInjectionName); - } - - assert('fullName must be a proper full name', this.isValidFullName(fullName)); - let normalizedName = this.normalize(fullName); - - let injections = this._injections[normalizedName] || (this._injections[normalizedName] = []); - - injections.push({ property, specifier: normalizedInjectionName }); } /** @@ -612,34 +507,6 @@ export default class Registry implements IRegistry { isValidFullName(fullName: string): boolean { return VALID_FULL_NAME_REGEXP.test(fullName); } - - getInjections(fullName: string) { - let injections = this._injections[fullName]; - if (this.fallback !== null) { - let fallbackInjections = this.fallback.getInjections(fullName); - - if (fallbackInjections !== undefined) { - injections = - injections === undefined ? fallbackInjections : injections.concat(fallbackInjections); - } - } - - return injections; - } - - getTypeInjections(type: string): Injection[] { - let injections = this._typeInjections[type]; - if (this.fallback !== null) { - let fallbackInjections = this.fallback.getTypeInjections(type); - - if (fallbackInjections !== undefined) { - injections = - injections === undefined ? fallbackInjections : injections.concat(fallbackInjections); - } - } - - return injections; - } } export declare class DebugRegistry extends Registry { diff --git a/packages/@ember/-internals/container/tests/container_test.js b/packages/@ember/-internals/container/tests/container_test.js index 8a9a3311887..fbe16b0deb4 100644 --- a/packages/@ember/-internals/container/tests/container_test.js +++ b/packages/@ember/-internals/container/tests/container_test.js @@ -223,84 +223,6 @@ moduleFor( assert.equal(postController, container.lookup('controller:post')); } - ['@test uses create time injections if factory has no extend'](assert) { - let registry = new Registry(); - let container = registry.container(); - let AppleController = factory(); - let PostController = factory(); - - PostController.extend = undefined; // remove extend - - registry.register('controller:apple', AppleController); - registry.register('controller:post', PostController); - registry.injection('controller:post', 'apple', 'controller:apple'); - - let postController = container.lookup('controller:post'); - - assert.ok( - postController.apple instanceof AppleController, - 'instance receives an apple of instance AppleController' - ); - } - - ["@test A factory type with a registered injection's instances receive that injection"]( - assert - ) { - let registry = new Registry(); - let container = registry.container(); - let PostController = factory(); - let Store = factory(); - - registry.register('controller:post', PostController); - registry.register('store:main', Store); - - registry.typeInjection('controller', 'store', 'store:main'); - - let postController = container.lookup('controller:post'); - let store = container.lookup('store:main'); - - assert.equal(postController.store, store); - } - - ['@test An individual factory with a registered injection receives the injection'](assert) { - let registry = new Registry(); - let container = registry.container(); - let PostController = factory(); - let Store = factory(); - - registry.register('controller:post', PostController); - registry.register('store:main', Store); - - registry.injection('controller:post', 'store', 'store:main'); - - let postController = container.lookup('controller:post'); - let store = container.lookup('store:main'); - - assert.equal(postController.store, store, 'has the correct store injected'); - } - - ['@test A factory with both type and individual injections'](assert) { - let registry = new Registry(); - let container = registry.container(); - let PostController = factory(); - let Store = factory(); - let Router = factory(); - - registry.register('controller:post', PostController); - registry.register('store:main', Store); - registry.register('router:main', Router); - - registry.injection('controller:post', 'store', 'store:main'); - registry.typeInjection('controller', 'router', 'router:main'); - - let postController = container.lookup('controller:post'); - let store = container.lookup('store:main'); - let router = container.lookup('router:main'); - - assert.equal(postController.store, store); - assert.equal(postController.router, router); - } - ['@test A non-singleton instance is never cached'](assert) { let registry = new Registry(); let container = registry.container(); @@ -341,43 +263,7 @@ moduleFor( }, /Failed to create an instance of 'controller:foo'/); } - ['@test Injecting a failed lookup raises an error']() { - let registry = new Registry(); - let container = registry.container(); - - let fooInstance = {}; - let fooFactory = {}; - - let Foo = { - create() { - return fooInstance; - }, - extend() { - return fooFactory; - }, - }; - - registry.register('model:foo', Foo); - registry.injection('model:foo', 'store', 'store:main'); - - expectAssertion(() => { - container.lookup('model:foo'); - }); - } - - ['@test Injecting a falsy value does not raise an error'](assert) { - let registry = new Registry(); - let container = registry.container(); - let ApplicationController = factory(); - - registry.register('controller:application', ApplicationController); - registry.register('user:current', null, { instantiate: false }); - registry.injection('controller:application', 'currentUser', 'user:current'); - - assert.strictEqual(container.lookup('controller:application').currentUser, null); - } - - ['@test The container returns same value each time even if the value is falsy'](assert) { + ['@test The container returns same value each time even if the value is falsey'](assert) { let registry = new Registry(); let container = registry.container(); @@ -386,30 +272,6 @@ moduleFor( assert.strictEqual(container.lookup('falsy:value'), container.lookup('falsy:value')); } - ['@test Destroying the container destroys any cached singletons'](assert) { - let registry = new Registry(); - let container = registry.container(); - let PostController = factory(); - let PostView = factory(); - let template = function () {}; - - registry.register('controller:post', PostController); - registry.register('view:post', PostView, { singleton: false }); - registry.register('template:post', template, { instantiate: false }); - - registry.injection('controller:post', 'postView', 'view:post'); - - let postController = container.lookup('controller:post'); - let postView = postController.postView; - - assert.ok(postView instanceof PostView, 'The non-singleton was injected'); - - container.destroy(); - - assert.ok(postController.isDestroyed, 'Singletons are destroyed'); - assert.ok(!postView.isDestroyed, 'Non-singletons are not destroyed'); - } - ['@test The container can use a registry hook to resolve factories lazily'](assert) { let registry = new Registry(); let container = registry.container(); @@ -509,27 +371,6 @@ moduleFor( assert.ok(postView1 !== postView2, 'The two lookups are different'); } - ['@test An injected non-singleton instance is never cached'](assert) { - let registry = new Registry(); - let container = registry.container(); - let PostView = factory(); - let PostViewHelper = factory(); - - registry.register('view:post', PostView, { singleton: false }); - registry.register('view_helper:post', PostViewHelper, { - singleton: false, - }); - registry.injection('view:post', 'viewHelper', 'view_helper:post'); - - let postView1 = container.lookup('view:post'); - let postView2 = container.lookup('view:post'); - - assert.ok( - postView1.viewHelper !== postView2.viewHelper, - 'Injected non-singletons are not cached' - ); - } - ['@test Factory resolves are cached'](assert) { let registry = new Registry(); let container = registry.container(); @@ -752,39 +593,6 @@ moduleFor( assert.notEqual(factory1, factory3); } - ['@test #factoryFor created instances come with instance injections'](assert) { - let registry = new Registry(); - let container = registry.container(); - - let Component = factory(); - let Ajax = factory(); - registry.register('component:foo-bar', Component); - registry.register('util:ajax', Ajax); - registry.injection('component:foo-bar', 'ajax', 'util:ajax'); - - let componentFactory = container.factoryFor('component:foo-bar'); - let component = componentFactory.create(); - - assert.ok(component.ajax); - assert.ok(component.ajax instanceof Ajax); - } - - ['@test #factoryFor options passed to create clobber injections'](assert) { - let registry = new Registry(); - let container = registry.container(); - - let Component = factory(); - let Ajax = factory(); - registry.register('component:foo-bar', Component); - registry.register('util:ajax', Ajax); - registry.injection('component:foo-bar', 'ajax', 'util:ajax'); - - let componentFactory = container.factoryFor('component:foo-bar'); - let instrance = componentFactory.create({ ajax: 'fetch' }); - - assert.equal(instrance.ajax, 'fetch'); - } - [`@test assert when calling lookup after destroy on a container`](assert) { let registry = new Registry(); let container = registry.container(); diff --git a/packages/@ember/-internals/container/tests/registry_test.js b/packages/@ember/-internals/container/tests/registry_test.js index 9981c6e32be..4630fa195c6 100644 --- a/packages/@ember/-internals/container/tests/registry_test.js +++ b/packages/@ember/-internals/container/tests/registry_test.js @@ -79,17 +79,6 @@ moduleFor( ); } - ['@test Throw exception when trying to inject `type:thing` on all type(s)']() { - let registry = new Registry(); - let PostController = factory(); - - registry.register('controller:post', PostController); - - expectAssertion(() => { - registry.typeInjection('controller', 'injected', 'controller:post'); - }, /Cannot inject a 'controller:post' on other controller\(s\)\./); - } - ['@test The registry can take a hook to resolve factories lazily'](assert) { let PostController = factory(); let resolver = { @@ -154,26 +143,6 @@ moduleFor( ); } - ['@test The registry normalizes names when injecting'](assert) { - let registry = new Registry(); - let PostController = factory(); - let user = { name: 'Stef' }; - - registry.normalize = function () { - return 'controller:post'; - }; - - registry.register('controller:post', PostController); - registry.register('user:post', user, { instantiate: false }); - registry.injection('controller:post', 'user', 'controller:normalized'); - - assert.deepEqual( - registry.resolve('controller:post'), - user, - 'Normalizes the name when injecting' - ); - } - ['@test cannot register an `undefined` factory']() { let registry = new Registry(); @@ -208,29 +177,6 @@ moduleFor( assert.strictEqual(registry.resolve('controller:apple'), FirstApple); } - ['@test registry.has should not accidentally cause injections on that factory to be run. (Mitigate merely on observing)']( - assert - ) { - assert.expect(1); - - let registry = new Registry(); - let FirstApple = factory('first'); - let SecondApple = factory('second'); - - SecondApple.extend = function () { - assert.ok( - false, - 'should not extend or touch the injected model, merely to inspect existence of another' - ); - }; - - registry.register('controller:apple', FirstApple); - registry.register('controller:second-apple', SecondApple); - registry.injection('controller:apple', 'badApple', 'controller:second-apple'); - - assert.ok(registry.has('controller:apple')); - } - ['@test registry.has should not error for invalid fullNames'](assert) { let registry = new Registry(); @@ -483,44 +429,6 @@ moduleFor( ); } - ['@test `getInjections` includes injections from a fallback registry'](assert) { - let fallback = new Registry(); - let registry = new Registry({ fallback: fallback }); - - assert.strictEqual( - registry.getInjections('model:user'), - undefined, - 'No injections in the primary registry' - ); - - fallback.injection('model:user', 'post', 'model:post'); - - assert.equal( - registry.getInjections('model:user').length, - 1, - 'Injections from the fallback registry are merged' - ); - } - - ['@test `getTypeInjections` includes type injections from a fallback registry'](assert) { - let fallback = new Registry(); - let registry = new Registry({ fallback: fallback }); - - assert.strictEqual( - registry.getTypeInjections('model'), - undefined, - 'No injections in the primary registry' - ); - - fallback.injection('model', 'source', 'source:main'); - - assert.equal( - registry.getTypeInjections('model').length, - 1, - 'Injections from the fallback registry are merged' - ); - } - ['@test `knownForType` contains keys for each item of a given type'](assert) { let registry = new Registry(); diff --git a/packages/@ember/-internals/extension-support/lib/container_debug_adapter.js b/packages/@ember/-internals/extension-support/lib/container_debug_adapter.js index 8923585ecc8..2d352fc15ab 100644 --- a/packages/@ember/-internals/extension-support/lib/container_debug_adapter.js +++ b/packages/@ember/-internals/extension-support/lib/container_debug_adapter.js @@ -1,5 +1,6 @@ import { classify, dasherize } from '@ember/string'; import { A as emberA, typeOf, Namespace, Object as EmberObject } from '@ember/-internals/runtime'; +import { getOwner } from '@ember/-internals/owner'; /** @module @ember/debug @@ -40,6 +41,12 @@ import { A as emberA, typeOf, Namespace, Object as EmberObject } from '@ember/-i @public */ export default EmberObject.extend({ + init() { + this._super(...arguments); + + this.resolver = getOwner(this).lookup('resolver-for-debugging:main'); + }, + /** The resolver instance of the application being debugged. This property will be injected diff --git a/packages/@ember/-internals/glimmer/lib/renderer.ts b/packages/@ember/-internals/glimmer/lib/renderer.ts index e4c5fe0be4d..85d64cecf5d 100644 --- a/packages/@ember/-internals/glimmer/lib/renderer.ts +++ b/packages/@ember/-internals/glimmer/lib/renderer.ts @@ -1,3 +1,4 @@ +import { privatize as P } from '@ember/-internals/container'; import { ENV } from '@ember/-internals/environment'; import { getOwner, Owner } from '@ember/-internals/owner'; import { getViewElement, getViewId } from '@ember/-internals/views'; @@ -290,14 +291,16 @@ export class Renderer { readonly _runtimeResolver: ResolverImpl; - static create(props: { - document: SimpleDocument; - env: { isInteractive: boolean; hasDOM: boolean }; - rootTemplate: TemplateFactory; - _viewRegistry: any; - builder: any; - }): Renderer { - let { document, env, rootTemplate, _viewRegistry, builder } = props; + static create(props: { _viewRegistry: any }): Renderer { + let { _viewRegistry } = props; + let document = getOwner(props).lookup('service:-document') as SimpleDocument; + let env = getOwner(props).lookup('-environment:main') as { + isInteractive: boolean; + hasDOM: boolean; + }; + let owner = getOwner(props); + let rootTemplate = owner.lookup(P`template:-root`) as TemplateFactory; + let builder = owner.lookup('service:-dom-builder') as IBuilder; return new this(getOwner(props), document, env, rootTemplate, _viewRegistry, builder); } @@ -311,7 +314,7 @@ export class Renderer { ) { this._owner = owner; this._rootTemplate = rootTemplate(owner); - this._viewRegistry = viewRegistry; + this._viewRegistry = viewRegistry || owner.lookup('-view-registry:main'); this._roots = []; this._removedRoots = []; this._builder = builder; diff --git a/packages/@ember/-internals/glimmer/lib/setup-registry.ts b/packages/@ember/-internals/glimmer/lib/setup-registry.ts index 4bb5844c9a5..4f1977fe5ba 100644 --- a/packages/@ember/-internals/glimmer/lib/setup-registry.ts +++ b/packages/@ember/-internals/glimmer/lib/setup-registry.ts @@ -1,5 +1,6 @@ import { privatize as P, Registry } from '@ember/-internals/container'; import { ENV } from '@ember/-internals/environment'; +import { getOwner } from '@ember/-internals/owner'; import { EMBER_MODERNIZED_BUILT_IN_COMPONENTS } from '@ember/canary-features'; import Component from './component'; import LegacyLinkTo from './components/-link-to'; @@ -16,16 +17,14 @@ import RootTemplate from './templates/root'; import OutletView from './views/outlet'; export function setupApplicationRegistry(registry: Registry): void { - registry.injection('renderer', 'env', '-environment:main'); - // because we are using injections we can't use instantiate false // we need to use bind() to copy the function so factory for // association won't leak registry.register('service:-dom-builder', { - create({ bootOptions }: { bootOptions: { _renderMode: string } }) { - let { _renderMode } = bootOptions; + create(props) { + let env = getOwner(props).lookup('-environment:main') as { _renderMode: string }; - switch (_renderMode) { + switch (env._renderMode) { case 'serialize': return serializeBuilder.bind(null); case 'rehydrate': @@ -35,14 +34,10 @@ export function setupApplicationRegistry(registry: Registry): void { } }, }); - registry.injection('service:-dom-builder', 'bootOptions', '-environment:main'); - registry.injection('renderer', 'builder', 'service:-dom-builder'); registry.register(P`template:-root`, RootTemplate as any); - registry.injection('renderer', 'rootTemplate', P`template:-root`); registry.register('renderer:-dom', Renderer); - registry.injection('renderer', 'document', 'service:-document'); } export function setupEngineRegistry(registry: Registry): void { @@ -50,7 +45,6 @@ export function setupEngineRegistry(registry: Registry): void { registry.register('view:-outlet', OutletView); registry.register('template:-outlet', OutletTemplate as any); - registry.injection('view:-outlet', 'template', 'template:-outlet'); registry.optionsForType('helper', { instantiate: false }); diff --git a/packages/@ember/-internals/glimmer/lib/views/outlet.ts b/packages/@ember/-internals/glimmer/lib/views/outlet.ts index 871a26a5837..e6822d38564 100644 --- a/packages/@ember/-internals/glimmer/lib/views/outlet.ts +++ b/packages/@ember/-internals/glimmer/lib/views/outlet.ts @@ -34,10 +34,10 @@ export default class OutletView { } static create(options: any): OutletView { - let { _environment, template: templateFactory } = options; + let { environment: _environment, application: namespace, template: templateFactory } = options; let owner = getOwner(options); let template = templateFactory(owner); - return new OutletView(_environment, owner, template); + return new OutletView(_environment, owner, template, namespace); } private ref: Reference; @@ -46,7 +46,8 @@ export default class OutletView { constructor( private _environment: BootEnvironment, public owner: Owner, - public template: Template + public template: Template, + public namespace: any ) { let outletStateTag = createTag(); let outletState: OutletState = { diff --git a/packages/@ember/-internals/glimmer/tests/integration/outlet-test.js b/packages/@ember/-internals/glimmer/tests/integration/outlet-test.js index 8c0ed82f978..193ee68354c 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/outlet-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/outlet-test.js @@ -7,8 +7,9 @@ moduleFor( super(...arguments); let CoreOutlet = this.owner.factoryFor('view:-outlet'); - - this.component = CoreOutlet.create(); + let outletTemplateFactory = this.owner.lookup('template:-outlet'); + let environment = this.owner.lookup('-environment:main'); + this.component = CoreOutlet.create({ environment, template: outletTemplateFactory }); } ['@test should not error when initial rendered template is undefined']() { diff --git a/packages/@ember/-internals/routing/lib/system/router.ts b/packages/@ember/-internals/routing/lib/system/router.ts index 384e5c11c25..f2807c31e4d 100644 --- a/packages/@ember/-internals/routing/lib/system/router.ts +++ b/packages/@ember/-internals/routing/lib/system/router.ts @@ -653,7 +653,10 @@ class EmberRouter extends EmberObject.extend(Evented) implements Evented { if (!this._toplevelView) { let owner = getOwner(this); let OutletView = owner.factoryFor('view:-outlet')!; - this._toplevelView = OutletView.create(); + let application = owner.lookup('application:main'); + let environment = owner.lookup('-environment:main'); + let template = owner.lookup('template:-outlet'); + this._toplevelView = OutletView.create({ environment, template, application }); this._toplevelView.setOutletState(liveRoutes as GlimmerOutletState); let instance: any = owner.lookup('-application-instance:main'); if (instance) { diff --git a/packages/@ember/-internals/routing/tests/system/route_test.js b/packages/@ember/-internals/routing/tests/system/route_test.js index bcf4bfa32a5..b2c5edc4206 100644 --- a/packages/@ember/-internals/routing/tests/system/route_test.js +++ b/packages/@ember/-internals/routing/tests/system/route_test.js @@ -64,38 +64,6 @@ moduleFor( runDestroy(owner); } - ["@test 'store' can be injected by data persistence frameworks"](assert) { - assert.expect(8); - runDestroy(route); - - let owner = buildOwner(); - - let post = { - id: 1, - }; - - let Store = EmberObject.extend({ - find(type, value) { - assert.ok(true, 'injected model was called'); - assert.equal(type, 'post', 'correct type was called'); - assert.equal(value, 1, 'correct value was called'); - return post; - }, - }); - - owner.register('route:index', EmberRoute); - owner.register('store:main', Store); - - owner.inject('route', 'store', 'store:main'); - - route = owner.lookup('route:index'); - - assert.equal(route.model({ post_id: 1 }), post, '#model returns the correct post'); - assert.equal(route.findModel('post', 1), post, '#findModel returns the correct post'); - - runDestroy(owner); - } - ["@test assert if 'store.find' method is not found"]() { runDestroy(route); diff --git a/packages/@ember/-internals/runtime/lib/system/core_object.js b/packages/@ember/-internals/runtime/lib/system/core_object.js index 05ad5cc77c1..bbfe9ba0d29 100644 --- a/packages/@ember/-internals/runtime/lib/system/core_object.js +++ b/packages/@ember/-internals/runtime/lib/system/core_object.js @@ -4,13 +4,7 @@ import { getFactoryFor, setFactoryFor } from '@ember/-internals/container'; import { getOwner } from '@ember/-internals/owner'; -import { - guidFor, - lookupDescriptor, - inspect, - makeArray, - isInternalSymbol, -} from '@ember/-internals/utils'; +import { guidFor, makeArray, isInternalSymbol } from '@ember/-internals/utils'; import { meta } from '@ember/-internals/meta'; import { PROXY_CONTENT, @@ -22,10 +16,9 @@ import { descriptorForProperty, isClassicDecorator, DEBUG_INJECTION_FUNCTIONS, - TrackedDescriptor, } from '@ember/-internals/metal'; import ActionHandler from '../mixins/action_handler'; -import { assert, deprecate } from '@ember/debug'; +import { assert } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; import { _WeakSet as WeakSet } from '@glimmer/util'; import { destroy, isDestroying, isDestroyed, registerDestructor } from '@glimmer/destroyable'; @@ -61,21 +54,6 @@ function initialize(obj, properties) { !(properties instanceof Mixin) ); - let injectedProperties; - if (DEBUG) { - // these are all the implicit injectinos - injectedProperties = []; - - let factory = getFactoryFor(obj); - if (factory) { - for (let injection in factory.injections) { - if (factory.injections[injection] === properties[injection]) { - injectedProperties.push(injection); - } - } - } - } - let concatenatedProperties = obj.concatenatedProperties; let mergedProperties = obj.mergedProperties; let hasConcatenatedProps = @@ -124,85 +102,12 @@ function initialize(obj, properties) { } if (isDescriptor) { - if (DEBUG && injectedProperties.indexOf(keyName) !== -1) { - // need to check if implicit injection owner.inject('component:my-component', 'foo', 'service:bar') does not match explicit injection @service foo - // implicit injection takes precedence so need to tell user to rename property on obj - let isInjectedProperty = DEBUG_INJECTION_FUNCTIONS.has(possibleDesc._getter); - if (isInjectedProperty && value !== possibleDesc.get(obj, keyName)) { - implicitInjectionDeprecation( - keyName, - `You have explicitly defined a service injection for the '${keyName}' property on ${inspect( - obj - )}. However, a different service or value was injected via implicit injections which overrode your explicit injection. Implicit injections have been deprecated, and will be removed in the near future. In order to prevent breakage, you should inject the same value explicitly that is currently being injected implicitly.` - ); - } else if (possibleDesc instanceof TrackedDescriptor) { - let descValue = possibleDesc.get(obj, keyName); - - if (value !== descValue) { - implicitInjectionDeprecation( - keyName, - `A value was injected implicitly on the '${keyName}' tracked property of an instance of ${inspect( - obj - )}, overwriting the original value which was ${inspect( - descValue - )}. Implicit injection is now deprecated, please add an explicit injection for this value. If the injected value is a service, consider using the @service decorator.` - ); - } - } else if (possibleDesc._setter === undefined) { - implicitInjectionDeprecation( - keyName, - `A value was injected implicitly on the '${keyName}' computed property of an instance of ${inspect( - obj - )}. Implicit injection is now deprecated, please add an explicit injection for this value. If the injected value is a service, consider using the @service decorator.` - ); - } - } - possibleDesc.set(obj, keyName, value); } else if (typeof obj.setUnknownProperty === 'function' && !(keyName in obj)) { obj.setUnknownProperty(keyName, value); } else { if (DEBUG) { - // If deprecation, either 1) an accessor descriptor or 2) class field declaration 3) only an implicit injection - let desc = lookupDescriptor(obj, keyName); - - if (injectedProperties.indexOf(keyName) === -1) { - // Value was not an injected property, define in like normal - defineProperty(obj, keyName, null, value, m); // setup mandatory setter - } else if (desc) { - // If the property is a value prop, and it isn't the expected value, - // then we can warn the user when they attempt to use the value - if ('value' in desc && desc.value !== value) { - // implicit injection does not match value descriptor set on object - defineSelfDestructingImplicitInjectionGetter( - obj, - keyName, - value, - `A value was injected implicitly on the '${keyName}' property of an instance of ${inspect( - obj - )}, overwriting the original value which was ${inspect( - desc.value - )}. Implicit injection is now deprecated, please add an explicit injection for this value. If the injected value is a service, consider using the @service decorator.` - ); - } else { - // Otherwise, the value is either a getter/setter, or it is the correct value. - // If it is a getter/setter, then we don't know what activating it might do - it could - // be that the user only defined a getter, and so the value will not be set at all. It - // could be that the setter is a no-op that does nothing. Both of these are valid ways - // to "override" an implicit injection, so we can't really warn here. So, assign the - // value like we would normally. - obj[keyName] = value; - } - } else { - defineSelfDestructingImplicitInjectionGetter( - obj, - keyName, - value, - `A value was injected implicitly on the '${keyName}' property of an instance of ${inspect( - obj - )}. Implicit injection is now deprecated, please add an explicit injection for this value. If the injected value is a service, consider using the @service decorator.` - ); - } + defineProperty(obj, keyName, null, value, m); // setup mandatory setter } else { obj[keyName] = value; } @@ -229,20 +134,6 @@ function initialize(obj, properties) { sendEvent(obj, 'init', undefined, undefined, undefined, m); } -function defineSelfDestructingImplicitInjectionGetter(obj, keyName, value, message) { - Object.defineProperty(obj, keyName, { - configurable: true, - enumerable: true, - get() { - // only want to deprecate on first access so we make this self destructing - Object.defineProperty(obj, keyName, { value }); - - implicitInjectionDeprecation(keyName, message); - return value; - }, - }); -} - /** `CoreObject` is the base class for all Ember constructs. It establishes a class system based on Ember's Mixin system, and provides the basis for the @@ -1183,16 +1074,4 @@ if (DEBUG) { }; } -function implicitInjectionDeprecation(keyName, msg = null) { - deprecate(msg, false, { - id: 'implicit-injections', - until: '4.0.0', - url: 'https://deprecations.emberjs.com/v3.x#toc_implicit-injections', - for: 'ember-source', - since: { - enabled: '3.26.0', - }, - }); -} - export default CoreObject; diff --git a/packages/@ember/-internals/runtime/tests/system/object/create_test.js b/packages/@ember/-internals/runtime/tests/system/object/create_test.js index 1a05abdc9c8..5a5faa60012 100644 --- a/packages/@ember/-internals/runtime/tests/system/object/create_test.js +++ b/packages/@ember/-internals/runtime/tests/system/object/create_test.js @@ -1,7 +1,6 @@ import { getFactoryFor, Registry } from '@ember/-internals/container'; -import { inspect } from '@ember/-internals/utils'; import { getOwner, setOwner } from '@ember/-internals/owner'; -import { computed, Mixin, observer, addObserver, alias, tracked } from '@ember/-internals/metal'; +import { computed, Mixin, observer, addObserver, alias } from '@ember/-internals/metal'; import Service, { inject as service } from '@ember/service'; import { DEBUG } from '@glimmer/env'; import EmberObject from '../../../lib/system/object'; @@ -36,7 +35,7 @@ moduleFor( assert.equal(obj.foo.bar, 'foo'); } - ['@test implicit injections raises deprecation'](assert) { + ['@test implicit injections raises deprecation']() { let owner = buildOwner(); class FooService extends Service { @@ -45,305 +44,11 @@ moduleFor( class FooObject extends EmberObject {} owner.register('service:foo', FooService); owner.register('foo:main', FooObject); - owner.inject('foo:main', 'foo', 'service:foo'); - let obj = owner.lookup('foo:main'); - let result; - expectDeprecation( - () => (result = obj.foo), - `A value was injected implicitly on the 'foo' property of an instance of ${inspect( - obj - )}. Implicit injection is now deprecated, please add an explicit injection for this value. If the injected value is a service, consider using the @service decorator.` - ); - - assert.equal(result.bar, 'foo'); - assert.equal(obj.foo.bar, 'foo'); - } - - ['@test implicit injections raises deprecation for old style EmberObject'](assert) { - let owner = buildOwner(); - - class FooService extends Service { - bar = 'foo'; - } - let FooObject = EmberObject.extend(); - owner.register('service:foo', FooService); - owner.register('foo:main', FooObject); - owner.inject('foo:main', 'foo', 'service:foo'); - - let obj = owner.lookup('foo:main'); - let result; - expectDeprecation( - () => (result = obj.foo), - `A value was injected implicitly on the 'foo' property of an instance of ${inspect( - obj - )}. Implicit injection is now deprecated, please add an explicit injection for this value. If the injected value is a service, consider using the @service decorator.` - ); - - assert.equal(result.bar, 'foo'); - assert.equal(obj.foo.bar, 'foo'); - } - - ['@test implicit injections does not raise a deprecation if explicit injection present']( - assert - ) { - expectNoDeprecation(); - - let owner = buildOwner(); - - class FooService extends Service { - bar = 'foo'; - } - class FooObject extends EmberObject { - @service foo; - } - owner.register('service:foo', FooService); - owner.register('foo:main', FooObject); - owner.inject('foo:main', 'foo', 'service:foo'); - - let obj = owner.lookup('foo:main'); - assert.equal(obj.foo.bar, 'foo'); - } - - ['@test raises deprecation if explicit injection is not the same as the implicit injection']( - assert - ) { - let owner = buildOwner(); - - class FooService extends Service { - bar = 'foo'; - } - class BarService extends Service { - bar = 'bar'; - } - class FooObject extends EmberObject { - @service foo; - } - owner.register('service:foo', FooService); - owner.register('service:bar', BarService); - owner.register('foo:main', FooObject); - owner.inject('foo:main', 'foo', 'service:bar'); - - let result; expectDeprecation( - () => (result = owner.lookup('foo:main')), - /You have explicitly defined a service injection for the 'foo' property on <.*>. However, a different service or value was injected via implicit injections which overrode your explicit injection. Implicit injections have been deprecated, and will be removed in the near future. In order to prevent breakage, you should inject the same value explicitly that is currently being injected implicitly./ + () => owner.inject('foo:main', 'foo', 'service:foo'), + /As of Ember 4.0.0, owner.inject no longer injects values into resolved instances, and calling the method has been deprecated. Since this method no longer does anything, it is fully safe to remove this injection. As an alternative to this API, you can refactor to explicitly inject `foo` on `foo:main`, or look it up directly using the `getOwner` API./ ); - assert.equal(result.foo.bar, 'bar'); - } - - ['@test does not raise deprecation if descriptor is a value and equal to the implicit deprecation']( - assert - ) { - expectNoDeprecation(); - - let owner = buildOwner(); - - class FooService extends Service { - bar = 'foo'; - } - class BarService extends Service { - bar = 'bar'; - } - class FooObject extends EmberObject { - foo = getOwner(this).lookup('service:foo'); - } - owner.register('service:foo', FooService); - owner.register('service:bar', BarService); - owner.register('foo:main', FooObject); - owner.inject('foo:main', 'foo', 'service:foo'); - - let result = owner.lookup('foo:main'); - assert.equal(result.foo.bar, 'foo'); - } - - ['@test does raise deprecation if descriptor is a value and not equal to the implicit deprecation']( - assert - ) { - let owner = buildOwner(); - - class FooService extends Service { - bar = 'foo'; - } - class BarService extends Service { - bar = 'bar'; - } - class FooObject extends EmberObject { - foo = getOwner(this).lookup('service:foo'); - } - owner.register('service:foo', FooService); - owner.register('service:bar', BarService); - owner.register('foo:main', FooObject); - owner.inject('foo:main', 'foo', 'service:bar'); - - expectDeprecation(() => { - let result = owner.lookup('foo:main'); - assert.equal(result.foo.bar, 'bar'); - }, /A value was injected implicitly on the 'foo' property of an instance of <.*>, overwriting the original value which was <.*>. Implicit injection is now deprecated, please add an explicit injection for this value/); - } - - ['@test does not raise deprecation if descriptor is a tracked property and equal to the implicit deprecation']( - assert - ) { - expectNoDeprecation(); - - let owner = buildOwner(); - - class FooService extends Service { - bar = 'foo'; - } - class BarService extends Service { - bar = 'bar'; - } - class FooObject extends EmberObject { - @tracked foo = getOwner(this).lookup('service:foo'); - } - owner.register('service:foo', FooService); - owner.register('service:bar', BarService); - owner.register('foo:main', FooObject); - owner.inject('foo:main', 'foo', 'service:foo'); - - let result = owner.lookup('foo:main'); - assert.equal(result.foo.bar, 'foo'); - } - - ['@test does raise deprecation if descriptor is a tracked property and not equal to the implicit deprecation']( - assert - ) { - let owner = buildOwner(); - - class FooService extends Service { - bar = 'foo'; - } - class BarService extends Service { - bar = 'bar'; - } - class FooObject extends EmberObject { - @tracked foo = getOwner(this).lookup('service:foo'); - } - owner.register('service:foo', FooService); - owner.register('service:bar', BarService); - owner.register('foo:main', FooObject); - owner.inject('foo:main', 'foo', 'service:bar'); - - expectDeprecation(() => { - let result = owner.lookup('foo:main'); - assert.equal(result.foo.bar, 'bar'); - }, /A value was injected implicitly on the 'foo' tracked property of an instance of <.*>, overwriting the original value which was <.*>. Implicit injection is now deprecated, please add an explicit injection for this value/); - } - - ['@test does not raise deprecation if descriptor is a computed property with a setter']( - assert - ) { - expectNoDeprecation(); - - let owner = buildOwner(); - - class FooService extends Service { - bar = 'foo'; - } - class BarService extends Service { - bar = 'bar'; - } - class FooObject extends EmberObject { - @computed - get foo() { - return getOwner(this).lookup('service:foo'); - } - - set foo(val) {} - } - owner.register('service:foo', FooService); - owner.register('service:bar', BarService); - owner.register('foo:main', FooObject); - owner.inject('foo:main', 'foo', 'service:foo'); - - let result = owner.lookup('foo:main'); - assert.equal(result.foo.bar, 'foo'); - } - - ['@test does raise assertion if descriptor is a computed property without a setter']() { - let owner = buildOwner(); - - class FooService extends Service { - bar = 'foo'; - } - class BarService extends Service { - bar = 'bar'; - } - class FooObject extends EmberObject { - @computed - get foo() { - return getOwner(this).lookup('service:foo'); - } - } - owner.register('service:foo', FooService); - owner.register('service:bar', BarService); - owner.register('foo:main', FooObject); - owner.inject('foo:main', 'foo', 'service:bar'); - - expectAssertion(() => { - expectDeprecation( - /A value was injected implicitly on the 'foo' computed property of an instance of <.*>. Implicit injection is now deprecated, please add an explicit injection for this value/ - ); - owner.lookup('foo:main'); - }, /Cannot override the computed property `foo` on <.*>./); - } - - ['@test does not raise deprecation if descriptor is a getter and equal to the implicit deprecation']( - assert - ) { - expectNoDeprecation(); - - let owner = buildOwner(); - - class FooService extends Service { - bar = 'foo'; - } - class BarService extends Service { - bar = 'bar'; - } - class FooObject extends EmberObject { - get foo() { - return getOwner(this).lookup('service:foo'); - } - - set foo(_) {} - } - owner.register('service:foo', FooService); - owner.register('service:bar', BarService); - owner.register('foo:main', FooObject); - owner.inject('foo:main', 'foo', 'service:foo'); - - let result = owner.lookup('foo:main'); - assert.equal(result.foo.bar, 'foo'); - } - - ['@test does not raise deprecation if descriptor is a getter and not equal to the implicit deprecation']( - assert - ) { - let owner = buildOwner(); - - class FooService extends Service { - bar = 'foo'; - } - class BarService extends Service { - bar = 'bar'; - } - class FooObject extends EmberObject { - get foo() { - return getOwner(this).lookup('service:foo'); - } - - set foo(_) {} - } - owner.register('service:foo', FooService); - owner.register('service:bar', BarService); - owner.register('foo:main', FooObject); - owner.inject('foo:main', 'foo', 'service:bar'); - - let result = owner.lookup('foo:main'); - assert.equal(result.foo.bar, 'foo'); } ['@test calls computed property setters'](assert) { diff --git a/packages/@ember/application/lib/application.js b/packages/@ember/application/lib/application.js index cdff77056c5..38f9406471a 100644 --- a/packages/@ember/application/lib/application.js +++ b/packages/@ember/application/lib/application.js @@ -1029,8 +1029,6 @@ const Application = Engine.extend({ } else { // node application.register('service:network', NodeNetworkService); } - - application.inject('route', 'network', 'service:network'); }; export default { @@ -1041,13 +1039,16 @@ const Application = Engine.extend({ ```app/routes/post.js import Route from '@ember/routing/route'; + import { inject as service } from '@ember/service'; // An example of how the (hypothetical) service is used in routes. - export default Route.extend({ + export default class IndexRoute extends Route { + @service network; + model(params) { return this.network.fetch(`/api/posts/${params.post_id}.json`); - }, + } afterModel(post) { if (post.isExternalContent) { @@ -1056,7 +1057,7 @@ const Application = Engine.extend({ return post; } } - }); + } ``` ```javascript diff --git a/packages/@ember/application/tests/application_test.js b/packages/@ember/application/tests/application_test.js index 899149411ea..ca013a37d27 100644 --- a/packages/@ember/application/tests/application_test.js +++ b/packages/@ember/application/tests/application_test.js @@ -12,7 +12,6 @@ import { ApplicationTestCase, AbstractTestCase, AutobootApplicationTestCase, - verifyInjection, verifyRegistration, runTask, } from 'internal-test-helpers'; @@ -126,7 +125,6 @@ moduleFor( verifyRegistration(assert, application, '-view-registry:main'); verifyRegistration(assert, application, 'route:basic'); verifyRegistration(assert, application, 'event_dispatcher:main'); - verifyInjection(assert, application, 'view:-outlet', 'namespace', 'application:main'); verifyRegistration(assert, application, 'location:auto'); verifyRegistration(assert, application, 'location:hash'); @@ -143,20 +141,12 @@ moduleFor( // DEBUGGING verifyRegistration(assert, application, 'resolver-for-debugging:main'); - verifyInjection( - assert, - application, - 'container-debug-adapter:main', - 'resolver', - 'resolver-for-debugging:main' - ); verifyRegistration(assert, application, 'container-debug-adapter:main'); verifyRegistration(assert, application, 'component-lookup:main'); verifyRegistration(assert, application, 'view:-outlet'); verifyRegistration(assert, application, 'renderer:-dom'); verifyRegistration(assert, application, 'template:-outlet'); - verifyInjection(assert, application, 'view:-outlet', 'template', 'template:-outlet'); assert.deepEqual( application.registeredOptionsForType('helper'), diff --git a/packages/@ember/application/tests/dependency_injection_test.js b/packages/@ember/application/tests/dependency_injection_test.js index aecc515b091..6ac4de6a61d 100644 --- a/packages/@ember/application/tests/dependency_injection_test.js +++ b/packages/@ember/application/tests/dependency_injection_test.js @@ -71,23 +71,5 @@ moduleFor( 'non-singleton lookup worked' ); } - - ['@test injections'](assert) { - expectDeprecation( - /A value was injected implicitly on the 'fruit' property of an instance of <.*>. Implicit injection is now deprecated, please add an explicit injection for this value/ - ); - - application.inject('model', 'fruit', 'fruit:favorite'); - application.inject('model:user', 'communication', 'communication:main'); - - let user = locator.lookup('model:user'); - let person = locator.lookup('model:person'); - let fruit = locator.lookup('fruit:favorite'); - - assert.equal(user.get('fruit'), fruit); - assert.equal(person.get('fruit'), fruit); - - assert.ok(application.Email.detectInstance(user.get('communication'))); - } } ); diff --git a/packages/@ember/engine/index.js b/packages/@ember/engine/index.js index 270e5d04869..00e76461c90 100644 --- a/packages/@ember/engine/index.js +++ b/packages/@ember/engine/index.js @@ -485,10 +485,6 @@ function commonSetupRegistry(registry) { registry.register('controller:basic', Controller, { instantiate: false }); - registry.injection('renderer', '_viewRegistry', '-view-registry:main'); - - registry.injection('view:-outlet', 'namespace', 'application:main'); - // Register the routing service... registry.register('service:-routing', RoutingService); @@ -496,8 +492,6 @@ function commonSetupRegistry(registry) { registry.register('resolver-for-debugging:main', registry.resolver, { instantiate: false, }); - registry.injection('container-debug-adapter:main', 'resolver', 'resolver-for-debugging:main'); - // Custom resolver authors may want to register their own ContainerDebugAdapter with this key registry.register('container-debug-adapter:main', ContainerDebugAdapter); diff --git a/packages/@ember/engine/instance.js b/packages/@ember/engine/instance.js index 5ae670a72b2..56d78227726 100644 --- a/packages/@ember/engine/instance.js +++ b/packages/@ember/engine/instance.js @@ -193,9 +193,6 @@ const EngineInstance = EmberObject.extend(RegistryProxyMixin, ContainerProxyMixi } singletons.forEach((key) => this.register(key, parent.lookup(key), { instantiate: false })); - - this.inject('view', '_environment', '-environment:main'); - this.inject('route', '_environment', '-environment:main'); }, }); @@ -211,8 +208,6 @@ EngineInstance.reopenClass({ if (!options) { return; } - - registry.injection('view', '_environment', '-environment:main'); }, }); diff --git a/packages/@ember/engine/tests/engine_test.js b/packages/@ember/engine/tests/engine_test.js index 8507fcc4d0d..650d6934b69 100644 --- a/packages/@ember/engine/tests/engine_test.js +++ b/packages/@ember/engine/tests/engine_test.js @@ -8,7 +8,6 @@ import { moduleFor, AbstractTestCase as TestCase, ModuleBasedTestResolver, - verifyInjection, verifyRegistration, } from 'internal-test-helpers'; @@ -60,8 +59,6 @@ moduleFor( `optionsForType 'view'` ); verifyRegistration(assert, engine, 'controller:basic'); - verifyInjection(assert, engine, 'renderer', '_viewRegistry', '-view-registry:main'); - verifyInjection(assert, engine, 'view:-outlet', 'namespace', 'application:main'); verifyRegistration(assert, engine, 'component:-text-field'); verifyRegistration(assert, engine, 'component:-checkbox'); @@ -73,19 +70,11 @@ moduleFor( // DEBUGGING verifyRegistration(assert, engine, 'resolver-for-debugging:main'); - verifyInjection( - assert, - engine, - 'container-debug-adapter:main', - 'resolver', - 'resolver-for-debugging:main' - ); verifyRegistration(assert, engine, 'container-debug-adapter:main'); verifyRegistration(assert, engine, 'component-lookup:main'); verifyRegistration(assert, engine, 'view:-outlet'); verifyRegistration(assert, engine, 'template:-outlet'); - verifyInjection(assert, engine, 'view:-outlet', 'template', 'template:-outlet'); assert.deepEqual( engine.registeredOptionsForType('helper'), { instantiate: false }, diff --git a/packages/ember/tests/ember-test-helpers-test.js b/packages/ember/tests/ember-test-helpers-test.js index 67d0769490e..f3e6ce6c747 100644 --- a/packages/ember/tests/ember-test-helpers-test.js +++ b/packages/ember/tests/ember-test-helpers-test.js @@ -46,7 +46,9 @@ module('@ember/test-helpers emulation test', function () { function setupRenderingContext(context) { let { owner } = context; let OutletView = owner.factoryFor('view:-outlet'); - let toplevelView = OutletView.create(); + let environment = owner.lookup('-environment:main'); + let outletTemplateFactory = owner.lookup('template:-outlet'); + let toplevelView = OutletView.create({ environment, template: outletTemplateFactory }); owner.register('-top-level-view:main', { create() { diff --git a/packages/internal-test-helpers/index.js b/packages/internal-test-helpers/index.js index 49cb9317178..5695bf2329f 100644 --- a/packages/internal-test-helpers/index.js +++ b/packages/internal-test-helpers/index.js @@ -38,4 +38,4 @@ export { } from './lib/test-resolver'; export { isEdge } from './lib/browser-detect'; -export { verifyInjection, verifyRegistration } from './lib/registry-check'; +export { verifyRegistration } from './lib/registry-check'; diff --git a/packages/internal-test-helpers/lib/registry-check.js b/packages/internal-test-helpers/lib/registry-check.js index dd75bf7c65a..cc33fdcb370 100644 --- a/packages/internal-test-helpers/lib/registry-check.js +++ b/packages/internal-test-helpers/lib/registry-check.js @@ -1,28 +1,3 @@ export function verifyRegistration(assert, owner, fullName) { assert.ok(owner.resolveRegistration(fullName), `has registration: ${fullName}`); } - -export function verifyInjection(assert, owner, fullName, property, injectionName) { - let registry = owner.__registry__; - let injections; - - if (fullName.indexOf(':') === -1) { - injections = registry.getTypeInjections(fullName); - } else { - injections = registry.getInjections(registry.normalize(fullName)); - } - - let normalizedName = registry.normalize(injectionName); - let hasInjection = false; - let injection; - - for (let i = 0, l = injections.length; i < l; i++) { - injection = injections[i]; - if (injection.property === property && injection.specifier === normalizedName) { - hasInjection = true; - break; - } - } - - assert.ok(hasInjection, `has injection: ${fullName}.${property} = ${injectionName}`); -} diff --git a/packages/internal-test-helpers/lib/test-cases/rendering.js b/packages/internal-test-helpers/lib/test-cases/rendering.js index b3c59286749..ed271628e2c 100644 --- a/packages/internal-test-helpers/lib/test-cases/rendering.js +++ b/packages/internal-test-helpers/lib/test-cases/rendering.js @@ -18,14 +18,12 @@ export default class RenderingTestCase extends AbstractTestCase { ownerOptions: this.getOwnerOptions(), resolver: this.getResolver(), bootOptions, + viewRegistry: Object.create(null), })); owner.register('-view-registry:main', Object.create(null), { instantiate: false }); owner.register('event_dispatcher:main', EventDispatcher); - // TODO: why didn't buildOwner do this for us? - owner.inject('renderer', '_viewRegistry', '-view-registry:main'); - this.renderer = this.owner.lookup('renderer:-dom'); this.element = document.querySelector('#qunit-fixture'); this.component = null; diff --git a/packages/internal-test-helpers/lib/test-cases/router-non-application.js b/packages/internal-test-helpers/lib/test-cases/router-non-application.js index 61faf22da91..ed31bb3f6ef 100644 --- a/packages/internal-test-helpers/lib/test-cases/router-non-application.js +++ b/packages/internal-test-helpers/lib/test-cases/router-non-application.js @@ -16,14 +16,12 @@ export default class RouterNonApplicationTestCase extends AbstractTestCase { ownerOptions: this.getOwnerOptions(), resolver: this.getResolver(), bootOptions, + viewRegistry: Object.create(null), })); owner.register('-view-registry:main', Object.create(null), { instantiate: false }); owner.register('event_dispatcher:main', EventDispatcher); - // TODO: why didn't buildOwner do this for us? - owner.inject('renderer', '_viewRegistry', '-view-registry:main'); - this.renderer = this.owner.lookup('renderer:-dom'); this.element = document.querySelector('#qunit-fixture'); this.component = null; diff --git a/tests/docs/expected.js b/tests/docs/expected.js index 0b18828dbf8..3b98b3f264d 100644 --- a/tests/docs/expected.js +++ b/tests/docs/expected.js @@ -31,7 +31,6 @@ module.exports = { '_helpers', '_hydrateUnsuppliedQueryParams', '_initializersRan', - '_injections', '_internalReset', '_invoke', '_lazyInjections', @@ -52,7 +51,6 @@ module.exports = { '_serializeQueryParams', '_setRouteName', '_stashNames', - '_typeInjections', '_typeOptions', '_unwatchInstance', '_updatingQPChanged', @@ -288,7 +286,6 @@ module.exports = { 'initializer', 'initState', 'inject', - 'injection', 'injectTestHelpers', 'input', 'insertAt', @@ -543,7 +540,6 @@ module.exports = { 'triggerAction', 'trySet', 'type', - 'typeInjection', 'typeOf', 'typeWatchers', 'unbound', diff --git a/tests/node/helpers/setup-component.js b/tests/node/helpers/setup-component.js index 7321695af4f..174c75c0b54 100644 --- a/tests/node/helpers/setup-component.js +++ b/tests/node/helpers/setup-component.js @@ -48,7 +48,8 @@ function setupComponentTest() { this._hasRendered = false; let OutletView = module.owner.factoryFor('view:-outlet'); let outletTemplateFactory = module.owner.lookup('template:-outlet'); - module.component = OutletView.create(); + let environment = module.owner.lookup('-environment:main'); + module.component = OutletView.create({ environment, template: outletTemplateFactory }); this._outletState = { render: { owner: module.owner || undefined, diff --git a/tests/node/visit-test.js b/tests/node/visit-test.js index a478b867bfe..47452946ae1 100644 --- a/tests/node/visit-test.js +++ b/tests/node/visit-test.js @@ -227,16 +227,16 @@ QUnit.module('Ember.Application - visit() Integration Tests', function (hooks) { }); QUnit.test('Resource-discovery setup', function (assert) { - this.service('network', { - init: function () { - this.set('requests', []); - }, + class Network { + constructor() { + this.requests = []; + } - fetch: function (url) { - this.get('requests').push(url); + fetch(url) { + this.requests.push(url); return Promise.resolve(); - }, - }); + } + } this.routes(function () { this.route('a'); @@ -246,9 +246,10 @@ QUnit.module('Ember.Application - visit() Integration Tests', function (hooks) { this.route('e'); }); + let network; this.route('a', { model: function () { - return this.network.fetch('/a'); + return network.fetch('/a'); }, afterModel: function () { this.replaceWith('b'); @@ -257,7 +258,7 @@ QUnit.module('Ember.Application - visit() Integration Tests', function (hooks) { this.route('b', { model: function () { - return this.network.fetch('/b'); + return network.fetch('/b'); }, afterModel: function () { this.replaceWith('c'); @@ -266,13 +267,13 @@ QUnit.module('Ember.Application - visit() Integration Tests', function (hooks) { this.route('c', { model: function () { - return this.network.fetch('/c'); + return network.fetch('/c'); }, }); this.route('d', { model: function () { - return this.network.fetch('/d'); + return network.fetch('/d'); }, afterModel: function () { this.replaceWith('e'); @@ -281,7 +282,7 @@ QUnit.module('Ember.Application - visit() Integration Tests', function (hooks) { this.route('e', { model: function () { - return this.network.fetch('/e'); + return network.fetch('/e'); }, }); @@ -302,31 +303,37 @@ QUnit.module('Ember.Application - visit() Integration Tests', function (hooks) { let App = this.createApplication(); - App.inject('route', 'network', 'service:network'); - function assertResources(url, resources) { + network = new Network(); + return App.visit(url, { isBrowser: false, shouldRender: false }).then(function (instance) { try { let viewRegistry = instance.lookup('-view-registry:main'); assert.strictEqual(Object.keys(viewRegistry).length, 0, 'did not create any views'); - let networkService = instance.lookup('service:network'); - assert.deepEqual(networkService.get('requests'), resources); + assert.deepEqual(network.requests, resources); } finally { instance.destroy(); } }, handleError(assert)); } - return Promise.all([ - assertResources('/a', ['/a', '/b', '/c']), - assertResources('/b', ['/b', '/c']), - assertResources('/c', ['/c']), - assertResources('/d', ['/d', '/e']), - assertResources('/e', ['/e']), - ]).then(function () { - assert.strictEqual(xFooInstances, 0, 'it should not create any x-foo components'); - }); + return assertResources('/a', ['/a', '/b', '/c']) + .then(() => { + return assertResources('/b', ['/b', '/c']); + }) + .then(() => { + return assertResources('/c', ['/c']); + }) + .then(() => { + return assertResources('/d', ['/d', '/e']); + }) + .then(() => { + return assertResources('/e', ['/e']); + }) + .then(() => { + assert.strictEqual(xFooInstances, 0, 'it should not create any x-foo components'); + }); }); QUnit.test('FastBoot: tagless components can render', function (assert) {