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

Simplify and modularize app/router initialization #10256

Merged
merged 11 commits into from
Jan 22, 2015
21 changes: 21 additions & 0 deletions FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,27 @@ for a detailed explanation.

## Feature Flags

* `ember-application-instance-initializers`

Splits apart initializers into two phases:

* Boot-time Initializers that receive a registry, and use it to set up
code structures
* Instance Initializers that receive an application instance, and use
it to set up application state per run of the application.

In FastBoot, each request will have its own run of the application,
and will only need to run the instance initializers.

In the future, tests will also be able to use this differentiation to
run just the instance initializers per-test.

With this change, `App.initializer` becomes a "boot-time" initializer,
and issues a deprecation warning if instances are accessed.

Apps should migrate any initializers that require instances to the new
`App.instanceInitializer` API.

* `ember-application-initializer-context`

Sets the context of the initializer function to its object instead of the
Expand Down
1 change: 1 addition & 0 deletions features.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"ember-testing-checkbox-helpers": null,
"ember-metal-stream": null,
"ember-htmlbars-each-with-index": true,
"ember-application-instance-initializers": null,
"ember-application-initializer-context": null
},
"debugStatements": [
Expand Down
12 changes: 10 additions & 2 deletions packages/container/lib/registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,21 @@ Registry.prototype = {

lookup: function(fullName, options) {
Ember.assert('Create a container on the registry (with `registry.container()`) before calling `lookup`.', this._defaultContainer);
Ember.deprecate('`lookup` should not be called on a Registry. Call `lookup` directly on an associated Container instead.');

if (Ember.FEATURES.isEnabled('ember-application-instance-initializers')) {
Ember.deprecate('`lookup` was called on a Registry. The `initializer` API no longer receives a container, and you should use an `instanceInitializer` to look up objects from the container.', { url: "http://emberjs.com/guides/deprecations#toc_deprecate-access-to-instances-in-initializers" });
}

return this._defaultContainer.lookup(fullName, options);
},

lookupFactory: function(fullName) {
Ember.assert('Create a container on the registry (with `registry.container()`) before calling `lookupFactory`.', this._defaultContainer);
Ember.deprecate('`lookupFactory` should not be called on a Registry. Call `lookupFactory` directly on an associated Container instead.');

if (Ember.FEATURES.isEnabled('ember-application-instance-initializers')) {
Ember.deprecate('`lookupFactory` was called on a Registry. The `initializer` API no longer receives a container, and you should use an `instanceInitializer` to look up objects from the container.', { url: "http://emberjs.com/guides/deprecations#toc_deprecate-access-to-instances-in-initializers" });
}

return this._defaultContainer.lookupFactory(fullName);
},

Expand Down
113 changes: 113 additions & 0 deletions packages/ember-application/lib/system/application-instance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/**
@module ember
@submodule ember-application
@private
*/

import EmberObject from "ember-runtime/system/object";
import run from "ember-metal/run_loop";

/**
The `ApplicationInstance` encapsulates all of the stateful aspects of a
running `Application`.

At a high-level, we break application boot into two distinct phases:

* Definition time, where all of the classes, templates, and other
dependencies are loaded (typically in the browser).
* Run time, where we begin executing the application once everything
has loaded.

Definition time can be expensive and only needs to happen once since it is
an idempotent operation. For example, between test runs and FastBoot
requests, the application stays the same. It is only the state that we want
to reset.

That state is what the `ApplicationInstance` manages: it is responsible for
creating the container that contains all application state, and disposing of
it once the particular test run or FastBoot request has finished.
*/

export default EmberObject.extend({
/**
The application instance's container. The container stores all of the
instance-specific state for this application run.

@property {Ember.Container} container
*/
container: null,

/**
The application's registry. The registry contains the classes, templates,
and other code that makes up the application.

@property {Ember.Registry} registry
*/
registry: null,

/**
The DOM events for which the event dispatcher should listen.

By default, the application's `Ember.EventDispatcher` listens
for a set of standard DOM events, such as `mousedown` and
`keyup`, and delegates them to your application's `Ember.View`
instances.

@private
@property {Object} customEvents
*/
customEvents: null,

/**
The root DOM element of the Application as an element or a
[jQuery-compatible selector
string](http://api.jquery.com/category/selectors/).

@private
@property {String|DOMElement} rootElement
*/
rootElement: null,

init: function() {
this._super.apply(this, arguments);
this.container = this.registry.container();
},

/**
@private
*/
startRouting: function(isModuleBasedResolver) {
var router = this.container.lookup('router:main');
if (!router) { return; }

router.startRouting(isModuleBasedResolver);
},

/**
@private
*/
handleURL: function(url) {
var router = this.container.lookup('router:main');

return router.handleURL(url);
},

/**
@private
*/
setupEventDispatcher: function() {
var dispatcher = this.container.lookup('event_dispatcher:main');

dispatcher.setup(this.customEvents, this.rootElement);

return dispatcher;
},

/**
@private
*/
willDestroy: function() {
this._super.apply(this, arguments);
run(this.container, 'destroy');
}
});
Loading