Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CLEANUP beta] Deprecate owner.inject #19680

Merged
merged 1 commit into from Aug 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,5 +1,4 @@
export function initialize(/* application */) {
// application.inject('route', 'foo', 'service:foo');
}

export default {
Expand Down
@@ -1,5 +1,4 @@
export function initialize(/* appInstance */) {
// appInstance.inject('route', 'foo', 'service:foo');
}

export default {
Expand Down
1 change: 0 additions & 1 deletion node-tests/fixtures/initializer/initializer-nested.js
@@ -1,5 +1,4 @@
export function initialize(/* application */) {
// application.inject('route', 'foo', 'service:foo');
}

export default {
Expand Down
1 change: 0 additions & 1 deletion node-tests/fixtures/initializer/initializer.js
@@ -1,5 +1,4 @@
export function initialize(/* application */) {
// application.inject('route', 'foo', 'service:foo');
}

export default {
Expand Down
@@ -1,5 +1,4 @@
export function initialize(/* appInstance */) {
// appInstance.inject('route', 'foo', 'service:foo');
}

export default {
Expand Down
@@ -1,5 +1,4 @@
export function initialize(/* appInstance */) {
// appInstance.inject('route', 'foo', 'service:foo');
}

export default {
Expand Down
77 changes: 4 additions & 73 deletions packages/@ember/-internals/container/lib/container.ts
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -569,16 +507,9 @@ class FactoryManager<T, C> {
);
}

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);
Expand Down
167 changes: 17 additions & 150 deletions 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';

Expand All @@ -24,14 +24,12 @@ export interface KnownForTypeResult {

export interface IRegistry {
describe(fullName: string): string;
getInjections(fullName: string): Injection[];
getOption<K extends keyof TypeOptions>(
fullName: string,
optionName: K
): TypeOptions[K] | undefined;
getOptions(fullName: string): TypeOptions;
getOptionsForType(type: string): TypeOptions;
getTypeInjections(type: string): Injection[];
knownForType(type: string): KnownForTypeResult;
makeToString<T, C>(factory: Factory<T, C>, fullName: string): string;
normalizeFullName(fullName: string): string;
Expand Down Expand Up @@ -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 = {}) {
Expand All @@ -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);
Expand Down Expand Up @@ -130,20 +123,6 @@ export default class Registry implements IRegistry {
@type InheritingDict
*/

/**
@private

@property _typeInjections
@type InheritingDict
*/

/**
@private

@property _injections
@type InheritingDict
*/

/**
@private

Expand Down Expand Up @@ -468,116 +447,32 @@ 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
@method injection
@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 });
}

/**
Expand Down Expand Up @@ -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 {
Expand Down