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

Clean up boot process #10271

Merged
merged 15 commits into from
Jan 30, 2015
10 changes: 9 additions & 1 deletion FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ for a detailed explanation.

## Feature Flags

* `ember-application-visit`

Provides an API for creating an application instance and specifying
an initial URL that it should route to. This is useful for testing
(you can have multiple instances of an app without having to run
serially and call `reset()` each time), as well as being critical to
for FastBoot.

* `ember-application-instance-initializers`

Splits apart initializers into two phases:
Expand Down Expand Up @@ -217,4 +225,4 @@ for a detailed explanation.
});
```

Added in [#10274](https://github.com/emberjs/ember.js/pull/10274)
Added in [#10274](https://github.com/emberjs/ember.js/pull/10274)
3 changes: 2 additions & 1 deletion features.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"ember-htmlbars-each-with-index": true,
"ember-application-instance-initializers": null,
"ember-application-initializer-context": null,
"ember-router-willtransition": true
"ember-router-willtransition": true,
"ember-application-visit": null
},
"debugStatements": [
"Ember.warn",
Expand Down
8 changes: 4 additions & 4 deletions packages/container/lib/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,8 @@ function injectionsFor(container, fullName) {
var type = splitName[0];

var injections = buildInjections(container,
registry.typeInjections[type],
registry.injections[fullName]);
registry.getTypeInjections(type),
registry.getInjections(fullName));
injections._debugContainerKey = fullName;
injections.container = container;

Expand All @@ -284,8 +284,8 @@ function factoryInjectionsFor(container, fullName) {
var type = splitName[0];

var factoryInjections = buildInjections(container,
registry.factoryTypeInjections[type],
registry.factoryInjections[fullName]);
registry.getFactoryTypeInjections(type),
registry.getFactoryInjections(fullName));
factoryInjections._debugContainerKey = fullName;

return factoryInjections;
Expand Down
120 changes: 93 additions & 27 deletions packages/container/lib/registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,33 @@ var VALID_FULL_NAME_REGEXP = /^[^:]+.+:[^:]+$/;
@class Registry
*/
function Registry(options) {
this.fallback = options && options.fallback ? options.fallback : null;

this.resolver = options && options.resolver ? options.resolver : function() {};

this.registrations = dictionary(options && options.registrations ? options.registrations : null);
this.typeInjections = dictionary(options && options.typeInjections ? options.typeInjections : null);
this.injections = dictionary(null);
this.factoryTypeInjections = dictionary(null);
this.factoryInjections = dictionary(null);

this._normalizeCache = dictionary(null);
this._resolveCache = dictionary(null);
this._typeInjections = dictionary(null);
this._injections = dictionary(null);
this._factoryTypeInjections = dictionary(null);
this._factoryInjections = dictionary(null);

this._normalizeCache = dictionary(null);
this._resolveCache = dictionary(null);

this._options = dictionary(options && options.options ? options.options : null);
this._typeOptions = dictionary(options && options.typeOptions ? options.typeOptions : null);
this._options = dictionary(null);
this._typeOptions = dictionary(null);
}

Registry.prototype = {
/**
A backup registry for resolving registrations when no matches can be found.

@property fallback
@type Registry
*/
fallback: null,

/**
@property resolver
@type function
Expand All @@ -47,28 +58,36 @@ Registry.prototype = {
registrations: null,

/**
@property typeInjections
@private

@property _typeInjections
@type InheritingDict
*/
typeInjections: null,
_typeInjections: null,

/**
@property injections
@private

@property _injections
@type InheritingDict
*/
injections: null,
_injections: null,

/**
@property factoryTypeInjections
@private

@property _factoryTypeInjections
@type InheritingDict
*/
factoryTypeInjections: null,
_factoryTypeInjections: null,

/**
@property factoryInjections
@private

@property _factoryInjections
@type InheritingDict
*/
factoryInjections: null,
_factoryInjections: null,

/**
@private
Expand Down Expand Up @@ -249,7 +268,11 @@ Registry.prototype = {
*/
resolve: function(fullName) {
Ember.assert('fullName must be a proper full name', this.validateFullName(fullName));
return resolve(this, this.normalize(fullName));
var factory = resolve(this, this.normalize(fullName));
if (factory === undefined && this.fallback) {
factory = this.fallback.resolve(fullName);
}
return factory;
},

/**
Expand Down Expand Up @@ -349,7 +372,11 @@ Registry.prototype = {
},

getOptionsForType: function(type) {
return this._typeOptions[type];
var optionsForType = this._typeOptions[type];
if (optionsForType === undefined && this.fallback) {
optionsForType = this.fallback.getOptionsForType(type);
}
return optionsForType;
},

/**
Expand All @@ -365,7 +392,11 @@ Registry.prototype = {

getOptions: function(fullName) {
var normalizedName = this.normalize(fullName);
return this._options[normalizedName];
var options = this._options[normalizedName];
if (options === undefined && this.fallback) {
options = this.fallback.getOptions(fullName);
}
return options;
},

getOption: function(fullName, optionName) {
Expand All @@ -378,8 +409,11 @@ Registry.prototype = {
var type = fullName.split(':')[0];
options = this._typeOptions[type];

if (options) {
if (options && options[optionName] !== undefined) {
return options[optionName];

} else if (this.fallback) {
return this.fallback.getOption(fullName, optionName);
}
},

Expand Down Expand Up @@ -435,8 +469,8 @@ Registry.prototype = {
'` as a different type and perform the typeInjection.');
}

var injections = this.typeInjections[type] ||
(this.typeInjections[type] = []);
var injections = this._typeInjections[type] ||
(this._typeInjections[type] = []);

injections.push({
property: property,
Expand Down Expand Up @@ -500,8 +534,8 @@ Registry.prototype = {
Ember.assert('fullName must be a proper full name', this.validateFullName(fullName));
var normalizedName = this.normalize(fullName);

var injections = this.injections[normalizedName] ||
(this.injections[normalizedName] = []);
var injections = this._injections[normalizedName] ||
(this._injections[normalizedName] = []);

injections.push({
property: property,
Expand Down Expand Up @@ -540,8 +574,8 @@ Registry.prototype = {
@param {String} fullName
*/
factoryTypeInjection: function(type, property, fullName) {
var injections = this.factoryTypeInjections[type] ||
(this.factoryTypeInjections[type] = []);
var injections = this._factoryTypeInjections[type] ||
(this._factoryTypeInjections[type] = []);

injections.push({
property: property,
Expand Down Expand Up @@ -609,7 +643,7 @@ Registry.prototype = {
return this.factoryTypeInjection(normalizedName, property, normalizedInjectionName);
}

var injections = this.factoryInjections[normalizedName] || (this.factoryInjections[normalizedName] = []);
var injections = this._factoryInjections[normalizedName] || (this._factoryInjections[normalizedName] = []);

injections.push({
property: property,
Expand Down Expand Up @@ -652,6 +686,38 @@ Registry.prototype = {
}
}

return injections;
},

getInjections: function(fullName) {
var injections = this._injections[fullName] || [];
if (this.fallback) {
injections = injections.concat(this.fallback.getInjections(fullName));
}
return injections;
},

getTypeInjections: function(type) {
var injections = this._typeInjections[type] || [];
if (this.fallback) {
injections = injections.concat(this.fallback.getTypeInjections(type));
}
return injections;
},

getFactoryInjections: function(fullName) {
var injections = this._factoryInjections[fullName] || [];
if (this.fallback) {
injections = injections.concat(this.fallback.getFactoryInjections(fullName));
}
return injections;
},

getFactoryTypeInjections: function(type) {
var injections = this._factoryTypeInjections[type] || [];
if (this.fallback) {
injections = injections.concat(this.fallback.getFactoryTypeInjections(type));
}
return injections;
}
};
Expand Down
72 changes: 71 additions & 1 deletion packages/container/tests/registry_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ test("The registry can take a hook to resolve factories lazily", function() {
strictEqual(registry.resolve('controller:post'), PostController, "The correct factory was provided");
});

test("The registry respect the resolver hook for `has`", function() {
test("The registry respects the resolver hook for `has`", function() {
var registry = new Registry();
var PostController = factory();

Expand Down Expand Up @@ -275,3 +275,73 @@ test("registry.container creates an associated container", function() {
ok(postController instanceof PostController, "The lookup is an instance of the registered factory");
strictEqual(registry._defaultContainer, container, "_defaultContainer is set to the first created container and used for Ember 1.x Container compatibility");
});

test("`resolve` can be handled by a fallback registry", function() {
var fallback = new Registry();

var registry = new Registry({ fallback: fallback });
var PostController = factory();

fallback.register('controller:post', PostController);

var PostControllerFactory = registry.resolve('controller:post');

ok(PostControllerFactory, 'factory is returned');
ok(PostControllerFactory.create() instanceof PostController, "The return of factory.create is an instance of PostController");
});

test("`has` can be handled by a fallback registry", function() {
var fallback = new Registry();

var registry = new Registry({ fallback: fallback });
var PostController = factory();

fallback.register('controller:post', PostController);

equal(registry.has('controller:post'), true, "Fallback registry is checked for registration");
});

test("`getInjections` includes injections from a fallback registry", function() {
var fallback = new Registry();
var registry = new Registry({ fallback: fallback });

equal(registry.getInjections('model:user').length, 0, "No injections in the primary registry");

fallback.injection('model:user', 'post', 'model:post');

equal(registry.getInjections('model:user').length, 1, "Injections from the fallback registry are merged");
});

test("`getTypeInjections` includes type injections from a fallback registry", function() {
var fallback = new Registry();
var registry = new Registry({ fallback: fallback });

equal(registry.getTypeInjections('model').length, 0, "No injections in the primary registry");

fallback.injection('model', 'source', 'source:main');

equal(registry.getTypeInjections('model').length, 1, "Injections from the fallback registry are merged");
});

test("`getFactoryInjections` includes factory injections from a fallback registry", function() {
var fallback = new Registry();
var registry = new Registry({ fallback: fallback });

equal(registry.getFactoryInjections('model:user').length, 0, "No factory injections in the primary registry");

fallback.factoryInjection('model:user', 'store', 'store:main');

equal(registry.getFactoryInjections('model:user').length, 1, "Factory injections from the fallback registry are merged");
});


test("`getFactoryTypeInjections` includes factory type injections from a fallback registry", function() {
var fallback = new Registry();
var registry = new Registry({ fallback: fallback });

equal(registry.getFactoryTypeInjections('model').length, 0, "No factory type injections in the primary registry");

fallback.factoryInjection('model', 'store', 'store:main');

equal(registry.getFactoryTypeInjections('model').length, 1, "Factory type injections from the fallback registry are merged");
});
Loading