From ffa7ab1ce7a9f9d806726bb00941a1f65000a3a7 Mon Sep 17 00:00:00 2001 From: Dan Gebhardt Date: Thu, 3 Dec 2015 23:24:31 -0500 Subject: [PATCH 01/10] [FEATURE ember-application-engines] Initial addition of Engine + EngineInstance --- .../lib/system/application-instance.js | 11 +++---- .../lib/system/application.js | 8 ++--- .../lib/system/engine-instance.js | 31 +++++++++++++++++++ .../ember-application/lib/system/engine.js | 30 ++++++++++++++++++ .../tests/system/engine_instance_test.js | 22 +++++++++++++ .../tests/system/engine_test.js | 18 +++++++++++ 6 files changed, 109 insertions(+), 11 deletions(-) create mode 100644 packages/ember-application/lib/system/engine-instance.js create mode 100644 packages/ember-application/lib/system/engine.js create mode 100644 packages/ember-application/tests/system/engine_instance_test.js create mode 100644 packages/ember-application/tests/system/engine_test.js diff --git a/packages/ember-application/lib/system/application-instance.js b/packages/ember-application/lib/system/application-instance.js index bc38f35b3b6..a5d2dfcff7f 100644 --- a/packages/ember-application/lib/system/application-instance.js +++ b/packages/ember-application/lib/system/application-instance.js @@ -7,18 +7,17 @@ import { deprecate } from 'ember-metal/debug'; import isEnabled from 'ember-metal/features'; import { get } from 'ember-metal/property_get'; import { set } from 'ember-metal/property_set'; -import EmberObject from 'ember-runtime/system/object'; import run from 'ember-metal/run_loop'; import { computed } from 'ember-metal/computed'; -import ContainerProxy from 'ember-runtime/mixins/container_proxy'; import DOMHelper from 'ember-htmlbars/system/dom-helper'; import Registry from 'container/registry'; -import RegistryProxy, { buildFakeRegistryWithDeprecations } from 'ember-runtime/mixins/registry_proxy'; +import { buildFakeRegistryWithDeprecations } from 'ember-runtime/mixins/registry_proxy'; import Renderer from 'ember-metal-views/renderer'; import assign from 'ember-metal/assign'; import environment from 'ember-metal/environment'; import RSVP from 'ember-runtime/ext/rsvp'; import jQuery from 'ember-views/system/jquery'; +import EngineInstance from './engine-instance'; let BootOptions; @@ -45,12 +44,10 @@ let BootOptions; @public @class Ember.ApplicationInstance - @extends Ember.Object - @uses RegistryProxyMixin - @uses ContainerProxyMixin + @extends Ember.EngineInstance */ -let ApplicationInstance = EmberObject.extend(RegistryProxy, ContainerProxy, { +let ApplicationInstance = EngineInstance.extend({ /** The `Application` for which this is an instance. diff --git a/packages/ember-application/lib/system/application.js b/packages/ember-application/lib/system/application.js index 2ae346e2494..a87c28b1f30 100644 --- a/packages/ember-application/lib/system/application.js +++ b/packages/ember-application/lib/system/application.js @@ -12,7 +12,6 @@ import { get } from 'ember-metal/property_get'; import { set } from 'ember-metal/property_set'; import EmptyObject from 'ember-metal/empty_object'; import { runLoadHooks } from 'ember-runtime/system/lazy_load'; -import Namespace from 'ember-runtime/system/namespace'; import DefaultResolver from 'ember-application/system/resolver'; import run from 'ember-metal/run_loop'; import { canInvoke } from 'ember-metal/utils'; @@ -40,9 +39,10 @@ import LinkToComponent from 'ember-routing-views/components/link-to'; import RoutingService from 'ember-routing/services/routing'; import ContainerDebugAdapter from 'ember-extension-support/container_debug_adapter'; import { _loaded } from 'ember-runtime/system/lazy_load'; -import RegistryProxy, { buildFakeRegistryWithDeprecations } from 'ember-runtime/mixins/registry_proxy'; +import { buildFakeRegistryWithDeprecations } from 'ember-runtime/mixins/registry_proxy'; import environment from 'ember-metal/environment'; import RSVP from 'ember-runtime/ext/rsvp'; +import Engine from './engine'; function props(obj) { var properties = []; @@ -208,12 +208,12 @@ var librariesRegistered = false; @class Application @namespace Ember - @extends Ember.Namespace + @extends Ember.Engine @uses RegistryProxyMixin @public */ -var Application = Namespace.extend(RegistryProxy, { +var Application = Engine.extend({ _suppressDeferredDeprecation: true, /** diff --git a/packages/ember-application/lib/system/engine-instance.js b/packages/ember-application/lib/system/engine-instance.js new file mode 100644 index 00000000000..be8487d7bcd --- /dev/null +++ b/packages/ember-application/lib/system/engine-instance.js @@ -0,0 +1,31 @@ +/** +@module ember +@submodule ember-application +*/ + +import EmberObject from 'ember-runtime/system/object'; +import ContainerProxy from 'ember-runtime/mixins/container_proxy'; +import RegistryProxy from 'ember-runtime/mixins/registry_proxy'; + +/** + The `EngineInstance` encapsulates all of the stateful aspects of a + running `Engine`. + + @public + @class Ember.EngineInstance + @extends Ember.Object + @uses RegistryProxyMixin + @uses ContainerProxyMixin +*/ + +let EngineInstance = EmberObject.extend(RegistryProxy, ContainerProxy, { + /** + The `Engine` for which this is an instance. + + @property {Ember.Engine} engine + @private + */ + engine: null +}); + +export default EngineInstance; diff --git a/packages/ember-application/lib/system/engine.js b/packages/ember-application/lib/system/engine.js new file mode 100644 index 00000000000..18d644d7eb6 --- /dev/null +++ b/packages/ember-application/lib/system/engine.js @@ -0,0 +1,30 @@ +/** +@module ember +@submodule ember-application +*/ +import Namespace from 'ember-runtime/system/namespace'; +import RegistryProxy from 'ember-runtime/mixins/registry_proxy'; + +/** + The `Engine` class contains core functionality for both applications and + engines. + + Each engine manages a registry that's used for dependency injection and + exposed through `RegistryProxy`. + + Engines also manage initializers and instance initializers. + + Engines can spawn `EngineInstance` instances via `buildInstance()`. + + @class Engine + @namespace Ember + @extends Ember.Namespace + @uses RegistryProxyMixin + @public +*/ + +let Engine = Namespace.extend(RegistryProxy, { + +}); + +export default Engine; diff --git a/packages/ember-application/tests/system/engine_instance_test.js b/packages/ember-application/tests/system/engine_instance_test.js new file mode 100644 index 00000000000..7e4ca9361ec --- /dev/null +++ b/packages/ember-application/tests/system/engine_instance_test.js @@ -0,0 +1,22 @@ +import Engine from 'ember-application/system/engine'; +import run from 'ember-metal/run_loop'; + +let engine, engineInstance; + +QUnit.module('Ember.EngineInstance', { + setup() { + run(function() { + engine = Engine.create({ router: null }); + }); + }, + + teardown() { + if (engineInstance) { + run(engineInstance, 'destroy'); + } + + if (engine) { + run(engine, 'destroy'); + } + } +}); diff --git a/packages/ember-application/tests/system/engine_test.js b/packages/ember-application/tests/system/engine_test.js new file mode 100644 index 00000000000..ce55a17374b --- /dev/null +++ b/packages/ember-application/tests/system/engine_test.js @@ -0,0 +1,18 @@ +import run from 'ember-metal/run_loop'; +import Engine from 'ember-application/system/engine'; + +var engine; + +QUnit.module('Ember.Engine', { + setup() { + run(function() { + engine = Engine.create({ router: null }); + }); + }, + + teardown() { + if (engine) { + run(engine, 'destroy'); + } + } +}); From 6efba8b8b2160c8fa224e3bc98e22d0e4b77022c Mon Sep 17 00:00:00 2001 From: Dan Gebhardt Date: Fri, 4 Dec 2015 17:18:21 -0500 Subject: [PATCH 02/10] [FEATURE ember-application-engines] Move initializers from Application to Engine. Initializers and instance initializers are a common concern for applications and engines. --- .../lib/system/application.js | 291 +---------------- .../ember-application/lib/system/engine.js | 293 +++++++++++++++++- 2 files changed, 293 insertions(+), 291 deletions(-) diff --git a/packages/ember-application/lib/system/application.js b/packages/ember-application/lib/system/application.js index a87c28b1f30..4e4e52a5fd2 100644 --- a/packages/ember-application/lib/system/application.js +++ b/packages/ember-application/lib/system/application.js @@ -2,19 +2,16 @@ @module ember @submodule ember-application */ -import DAG from 'dag-map'; import Registry from 'container/registry'; import Ember from 'ember-metal'; // Ember.libraries, LOG_VERSION, Namespace, BOOTED -import { assert, deprecate, debug } from 'ember-metal/debug'; +import { assert, debug } from 'ember-metal/debug'; import isEnabled from 'ember-metal/features'; import { get } from 'ember-metal/property_get'; import { set } from 'ember-metal/property_set'; -import EmptyObject from 'ember-metal/empty_object'; import { runLoadHooks } from 'ember-runtime/system/lazy_load'; import DefaultResolver from 'ember-application/system/resolver'; import run from 'ember-metal/run_loop'; -import { canInvoke } from 'ember-metal/utils'; import Controller from 'ember-runtime/controllers/controller'; import Renderer from 'ember-metal-views/renderer'; import DOMHelper from 'ember-htmlbars/system/dom-helper'; @@ -44,16 +41,6 @@ import environment from 'ember-metal/environment'; import RSVP from 'ember-runtime/ext/rsvp'; import Engine from './engine'; -function props(obj) { - var properties = []; - - for (var key in obj) { - properties.push(key); - } - - return properties; -} - var librariesRegistered = false; /** @@ -398,7 +385,7 @@ var Application = Engine.extend({ @return {Ember.Registry} the configured registry */ buildRegistry() { - var registry = this.__registry__ = Application.buildRegistry(this); + var registry = this.__registry__ = this.constructor.buildRegistry(this); return registry; }, @@ -737,66 +724,6 @@ var Application = Engine.extend({ run.join(this, handleReset); }, - /** - @private - @method instanceInitializer - */ - instanceInitializer(options) { - this.constructor.instanceInitializer(options); - }, - - /** - @private - @method runInitializers - */ - runInitializers() { - var App = this; - this._runInitializer('initializers', function(name, initializer) { - assert('No application initializer named \'' + name + '\'', !!initializer); - if (initializer.initialize.length === 2) { - deprecate('The `initialize` method for Application initializer \'' + name + '\' should take only one argument - `App`, an instance of an `Application`.', - false, - { - id: 'ember-application.app-initializer-initialize-arguments', - until: '3.0.0', - url: 'http://emberjs.com/deprecations/v2.x/#toc_initializer-arity' - }); - - initializer.initialize(App.__registry__, App); - } else { - initializer.initialize(App); - } - }); - }, - - /** - @private - @since 1.12.0 - @method runInstanceInitializers - */ - runInstanceInitializers(instance) { - this._runInitializer('instanceInitializers', function(name, initializer) { - assert('No instance initializer named \'' + name + '\'', !!initializer); - initializer.initialize(instance); - }); - }, - - _runInitializer(bucketName, cb) { - var initializersByName = get(this.constructor, bucketName); - var initializers = props(initializersByName); - var graph = new DAG(); - var initializer; - - for (var i = 0; i < initializers.length; i++) { - initializer = initializersByName[initializers[i]]; - graph.addEdges(initializer.name, initializer, initializer.before, initializer.after); - } - - graph.topsort(function (vertex) { - cb(vertex.name, vertex.value); - }); - }, - /** @private @method didBecomeReady @@ -898,10 +825,6 @@ var Application = Engine.extend({ if (this._globalsMode && this.__deprecatedInstance__) { this.__deprecatedInstance__.destroy(); } - }, - - initializer(options) { - this.constructor.initializer(options); } }); @@ -913,73 +836,6 @@ Object.defineProperty(Application.prototype, 'registry', { } }); -Application.reopenClass({ - /** - Instance initializers run after all initializers have run. Because - instance initializers run after the app is fully set up. We have access - to the store, container, and other items. However, these initializers run - after code has loaded and are not allowed to defer readiness. - - Instance initializer receives an object which has the following attributes: - `name`, `before`, `after`, `initialize`. The only required attribute is - `initialize`, all others are optional. - - * `name` allows you to specify under which name the instanceInitializer is - registered. This must be a unique name, as trying to register two - instanceInitializer with the same name will result in an error. - - ```javascript - Ember.Application.instanceInitializer({ - name: 'namedinstanceInitializer', - - initialize: function(application) { - Ember.debug('Running namedInitializer!'); - } - }); - ``` - - * `before` and `after` are used to ensure that this initializer is ran prior - or after the one identified by the value. This value can be a single string - or an array of strings, referencing the `name` of other initializers. - - * See Ember.Application.initializer for discussion on the usage of before - and after. - - Example instanceInitializer to preload data into the store. - - ```javascript - Ember.Application.initializer({ - name: 'preload-data', - - initialize: function(application) { - var userConfig, userConfigEncoded, store; - // We have a HTML escaped JSON representation of the user's basic - // configuration generated server side and stored in the DOM of the main - // index.html file. This allows the app to have access to a set of data - // without making any additional remote calls. Good for basic data that is - // needed for immediate rendering of the page. Keep in mind, this data, - // like all local models and data can be manipulated by the user, so it - // should not be relied upon for security or authorization. - // - // Grab the encoded data from the meta tag - userConfigEncoded = Ember.$('head meta[name=app-user-config]').attr('content'); - // Unescape the text, then parse the resulting JSON into a real object - userConfig = JSON.parse(unescape(userConfigEncoded)); - // Lookup the store - store = application.lookup('service:store'); - // Push the encoded JSON into the store - store.pushPayload(userConfig); - } - }); - ``` - - @method instanceInitializer - @param instanceInitializer - @public - */ - instanceInitializer: buildInitializerMethod('instanceInitializers', 'instance initializer') -}); - if (isEnabled('ember-application-visit')) { Application.reopen({ /** @@ -1190,129 +1046,6 @@ if (isEnabled('ember-application-visit')) { } Application.reopenClass({ - initializers: new EmptyObject(), - instanceInitializers: new EmptyObject(), - - /** - The goal of initializers should be to register dependencies and injections. - This phase runs once. Because these initializers may load code, they are - allowed to defer application readiness and advance it. If you need to access - the container or store you should use an InstanceInitializer that will be run - after all initializers and therefore after all code is loaded and the app is - ready. - - Initializer receives an object which has the following attributes: - `name`, `before`, `after`, `initialize`. The only required attribute is - `initialize`, all others are optional. - - * `name` allows you to specify under which name the initializer is registered. - This must be a unique name, as trying to register two initializers with the - same name will result in an error. - - ```javascript - Ember.Application.initializer({ - name: 'namedInitializer', - - initialize: function(application) { - Ember.debug('Running namedInitializer!'); - } - }); - ``` - - * `before` and `after` are used to ensure that this initializer is ran prior - or after the one identified by the value. This value can be a single string - or an array of strings, referencing the `name` of other initializers. - - An example of ordering initializers, we create an initializer named `first`: - - ```javascript - Ember.Application.initializer({ - name: 'first', - - initialize: function(application) { - Ember.debug('First initializer!'); - } - }); - - // DEBUG: First initializer! - ``` - - We add another initializer named `second`, specifying that it should run - after the initializer named `first`: - - ```javascript - Ember.Application.initializer({ - name: 'second', - after: 'first', - - initialize: function(application) { - Ember.debug('Second initializer!'); - } - }); - - // DEBUG: First initializer! - // DEBUG: Second initializer! - ``` - - Afterwards we add a further initializer named `pre`, this time specifying - that it should run before the initializer named `first`: - - ```javascript - Ember.Application.initializer({ - name: 'pre', - before: 'first', - - initialize: function(application) { - Ember.debug('Pre initializer!'); - } - }); - - // DEBUG: Pre initializer! - // DEBUG: First initializer! - // DEBUG: Second initializer! - ``` - - Finally we add an initializer named `post`, specifying it should run after - both the `first` and the `second` initializers: - - ```javascript - Ember.Application.initializer({ - name: 'post', - after: ['first', 'second'], - - initialize: function(application) { - Ember.debug('Post initializer!'); - } - }); - - // DEBUG: Pre initializer! - // DEBUG: First initializer! - // DEBUG: Second initializer! - // DEBUG: Post initializer! - ``` - - * `initialize` is a callback function that receives one argument, - `application`, on which you can operate. - - Example of using `application` to register an adapter: - - ```javascript - Ember.Application.initializer({ - name: 'api-adapter', - - initialize: function(application) { - application.register('api-adapter:main', ApiAdapter); - } - }); - ``` - - @method initializer - @param initializer {Object} - @public - */ - - initializer: buildInitializerMethod('initializers', 'initializer'), - /** This creates a registry with the default Ember naming conventions. @@ -1468,24 +1201,4 @@ function logLibraryVersions() { } } -function buildInitializerMethod(bucketName, humanName) { - return function(initializer) { - // If this is the first initializer being added to a subclass, we are going to reopen the class - // to make sure we have a new `initializers` object, which extends from the parent class' using - // prototypal inheritance. Without this, attempting to add initializers to the subclass would - // pollute the parent class as well as other subclasses. - if (this.superclass[bucketName] !== undefined && this.superclass[bucketName] === this[bucketName]) { - var attrs = {}; - attrs[bucketName] = Object.create(this[bucketName]); - this.reopenClass(attrs); - } - - assert('The ' + humanName + ' \'' + initializer.name + '\' has already been registered', !this[bucketName][initializer.name]); - assert('An ' + humanName + ' cannot be registered without an initialize function', canInvoke(initializer, 'initialize')); - assert('An ' + humanName + ' cannot be registered without a name property', initializer.name !== undefined); - - this[bucketName][initializer.name] = initializer; - }; -} - export default Application; diff --git a/packages/ember-application/lib/system/engine.js b/packages/ember-application/lib/system/engine.js index 18d644d7eb6..ca37375df4d 100644 --- a/packages/ember-application/lib/system/engine.js +++ b/packages/ember-application/lib/system/engine.js @@ -4,6 +4,21 @@ */ import Namespace from 'ember-runtime/system/namespace'; import RegistryProxy from 'ember-runtime/mixins/registry_proxy'; +import DAG from 'dag-map'; +import { get } from 'ember-metal/property_get'; +import { assert, deprecate } from 'ember-metal/debug'; +import { canInvoke } from 'ember-metal/utils'; +import EmptyObject from 'ember-metal/empty_object'; + +function props(obj) { + var properties = []; + + for (var key in obj) { + properties.push(key); + } + + return properties; +} /** The `Engine` class contains core functionality for both applications and @@ -19,12 +34,286 @@ import RegistryProxy from 'ember-runtime/mixins/registry_proxy'; @class Engine @namespace Ember @extends Ember.Namespace - @uses RegistryProxyMixin + @uses RegistryProxy @public */ - let Engine = Namespace.extend(RegistryProxy, { + /** + @private + @method initializer + */ + initializer(options) { + this.constructor.initializer(options); + }, + + /** + @private + @method instanceInitializer + */ + instanceInitializer(options) { + this.constructor.instanceInitializer(options); + }, + + /** + @private + @method runInitializers + */ + runInitializers() { + this._runInitializer('initializers', (name, initializer) => { + assert('No application initializer named \'' + name + '\'', !!initializer); + if (initializer.initialize.length === 2) { + deprecate('The `initialize` method for Application initializer \'' + name + '\' should take only one argument - `App`, an instance of an `Application`.', + false, + { + id: 'ember-application.app-initializer-initialize-arguments', + until: '3.0.0', + url: 'http://emberjs.com/deprecations/v2.x/#toc_initializer-arity' + }); + + initializer.initialize(this.__registry__, this); + } else { + initializer.initialize(this); + } + }); + }, + + /** + @private + @since 1.12.0 + @method runInstanceInitializers + */ + runInstanceInitializers(instance) { + this._runInitializer('instanceInitializers', (name, initializer) => { + assert('No instance initializer named \'' + name + '\'', !!initializer); + initializer.initialize(instance); + }); + }, + + _runInitializer(bucketName, cb) { + var initializersByName = get(this.constructor, bucketName); + var initializers = props(initializersByName); + var graph = new DAG(); + var initializer; + + for (var i = 0; i < initializers.length; i++) { + initializer = initializersByName[initializers[i]]; + graph.addEdges(initializer.name, initializer, initializer.before, initializer.after); + } + + graph.topsort(function (vertex) { + cb(vertex.name, vertex.value); + }); + } +}); + +Engine.reopenClass({ + initializers: new EmptyObject(), + instanceInitializers: new EmptyObject(), + + /** + The goal of initializers should be to register dependencies and injections. + This phase runs once. Because these initializers may load code, they are + allowed to defer application readiness and advance it. If you need to access + the container or store you should use an InstanceInitializer that will be run + after all initializers and therefore after all code is loaded and the app is + ready. + + Initializer receives an object which has the following attributes: + `name`, `before`, `after`, `initialize`. The only required attribute is + `initialize`, all others are optional. + + * `name` allows you to specify under which name the initializer is registered. + This must be a unique name, as trying to register two initializers with the + same name will result in an error. + + ```javascript + Ember.Application.initializer({ + name: 'namedInitializer', + + initialize: function(application) { + Ember.debug('Running namedInitializer!'); + } + }); + ``` + + * `before` and `after` are used to ensure that this initializer is ran prior + or after the one identified by the value. This value can be a single string + or an array of strings, referencing the `name` of other initializers. + + An example of ordering initializers, we create an initializer named `first`: + + ```javascript + Ember.Application.initializer({ + name: 'first', + + initialize: function(application) { + Ember.debug('First initializer!'); + } + }); + + // DEBUG: First initializer! + ``` + + We add another initializer named `second`, specifying that it should run + after the initializer named `first`: + + ```javascript + Ember.Application.initializer({ + name: 'second', + after: 'first', + + initialize: function(application) { + Ember.debug('Second initializer!'); + } + }); + + // DEBUG: First initializer! + // DEBUG: Second initializer! + ``` + Afterwards we add a further initializer named `pre`, this time specifying + that it should run before the initializer named `first`: + + ```javascript + Ember.Application.initializer({ + name: 'pre', + before: 'first', + + initialize: function(application) { + Ember.debug('Pre initializer!'); + } + }); + + // DEBUG: Pre initializer! + // DEBUG: First initializer! + // DEBUG: Second initializer! + ``` + + Finally we add an initializer named `post`, specifying it should run after + both the `first` and the `second` initializers: + + ```javascript + Ember.Application.initializer({ + name: 'post', + after: ['first', 'second'], + + initialize: function(application) { + Ember.debug('Post initializer!'); + } + }); + + // DEBUG: Pre initializer! + // DEBUG: First initializer! + // DEBUG: Second initializer! + // DEBUG: Post initializer! + ``` + + * `initialize` is a callback function that receives one argument, + `application`, on which you can operate. + + Example of using `application` to register an adapter: + + ```javascript + Ember.Application.initializer({ + name: 'api-adapter', + + initialize: function(application) { + application.register('api-adapter:main', ApiAdapter); + } + }); + ``` + + @method initializer + @param initializer {Object} + @public + */ + + initializer: buildInitializerMethod('initializers', 'initializer'), + + /** + Instance initializers run after all initializers have run. Because + instance initializers run after the app is fully set up. We have access + to the store, container, and other items. However, these initializers run + after code has loaded and are not allowed to defer readiness. + + Instance initializer receives an object which has the following attributes: + `name`, `before`, `after`, `initialize`. The only required attribute is + `initialize`, all others are optional. + + * `name` allows you to specify under which name the instanceInitializer is + registered. This must be a unique name, as trying to register two + instanceInitializer with the same name will result in an error. + + ```javascript + Ember.Application.instanceInitializer({ + name: 'namedinstanceInitializer', + + initialize: function(application) { + Ember.debug('Running namedInitializer!'); + } + }); + ``` + + * `before` and `after` are used to ensure that this initializer is ran prior + or after the one identified by the value. This value can be a single string + or an array of strings, referencing the `name` of other initializers. + + * See Ember.Application.initializer for discussion on the usage of before + and after. + + Example instanceInitializer to preload data into the store. + + ```javascript + Ember.Application.initializer({ + name: 'preload-data', + + initialize: function(application) { + var userConfig, userConfigEncoded, store; + // We have a HTML escaped JSON representation of the user's basic + // configuration generated server side and stored in the DOM of the main + // index.html file. This allows the app to have access to a set of data + // without making any additional remote calls. Good for basic data that is + // needed for immediate rendering of the page. Keep in mind, this data, + // like all local models and data can be manipulated by the user, so it + // should not be relied upon for security or authorization. + // + // Grab the encoded data from the meta tag + userConfigEncoded = Ember.$('head meta[name=app-user-config]').attr('content'); + // Unescape the text, then parse the resulting JSON into a real object + userConfig = JSON.parse(unescape(userConfigEncoded)); + // Lookup the store + store = application.lookup('service:store'); + // Push the encoded JSON into the store + store.pushPayload(userConfig); + } + }); + ``` + + @method instanceInitializer + @param instanceInitializer + @public + */ + instanceInitializer: buildInitializerMethod('instanceInitializers', 'instance initializer') }); +function buildInitializerMethod(bucketName, humanName) { + return function(initializer) { + // If this is the first initializer being added to a subclass, we are going to reopen the class + // to make sure we have a new `initializers` object, which extends from the parent class' using + // prototypal inheritance. Without this, attempting to add initializers to the subclass would + // pollute the parent class as well as other subclasses. + if (this.superclass[bucketName] !== undefined && this.superclass[bucketName] === this[bucketName]) { + var attrs = {}; + attrs[bucketName] = Object.create(this[bucketName]); + this.reopenClass(attrs); + } + + assert('The ' + humanName + ' \'' + initializer.name + '\' has already been registered', !this[bucketName][initializer.name]); + assert('An ' + humanName + ' cannot be registered without an initialize function', canInvoke(initializer, 'initialize')); + assert('An ' + humanName + ' cannot be registered without a name property', initializer.name !== undefined); + + this[bucketName][initializer.name] = initializer; + }; +} + export default Engine; From 7b0a7ecb5b9e863bded0094d8b7e5c1861e1d52f Mon Sep 17 00:00:00 2001 From: Dan Gebhardt Date: Fri, 4 Dec 2015 17:47:11 -0500 Subject: [PATCH 03/10] [FEATURE ember-application-engines] Refactor registry and resolver concerns for engines. Provide a spare base implementation of `buildRegistry` for `Engine`, which is extended by `Application`. Also, allow for a custom `Resolver` property on `Engine` (and by extension, `Application`). --- .../lib/system/application.js | 67 +----------- .../ember-application/lib/system/engine.js | 102 +++++++++++++++++- 2 files changed, 102 insertions(+), 67 deletions(-) diff --git a/packages/ember-application/lib/system/application.js b/packages/ember-application/lib/system/application.js index 4e4e52a5fd2..29bef8805cc 100644 --- a/packages/ember-application/lib/system/application.js +++ b/packages/ember-application/lib/system/application.js @@ -2,15 +2,11 @@ @module ember @submodule ember-application */ -import Registry from 'container/registry'; - import Ember from 'ember-metal'; // Ember.libraries, LOG_VERSION, Namespace, BOOTED import { assert, debug } from 'ember-metal/debug'; import isEnabled from 'ember-metal/features'; import { get } from 'ember-metal/property_get'; -import { set } from 'ember-metal/property_set'; import { runLoadHooks } from 'ember-runtime/system/lazy_load'; -import DefaultResolver from 'ember-application/system/resolver'; import run from 'ember-metal/run_loop'; import Controller from 'ember-runtime/controllers/controller'; import Renderer from 'ember-metal-views/renderer'; @@ -347,8 +343,6 @@ var Application = Engine.extend({ this.$ = jQuery; } - this.buildRegistry(); - registerLibraries(); logLibraryVersions(); @@ -377,19 +371,6 @@ var Application = Engine.extend({ } }, - /** - Build and configure the registry for the current application. - - @private - @method buildRegistry - @return {Ember.Registry} the configured registry - */ - buildRegistry() { - var registry = this.__registry__ = this.constructor.buildRegistry(this); - - return registry; - }, - /** Create an ApplicationInstance for this application. @@ -792,24 +773,6 @@ var Application = Engine.extend({ */ ready() { return this; }, - /** - Set this to provide an alternate class to `Ember.DefaultResolver` - - - @deprecated Use 'Resolver' instead - @property resolver - @public - */ - resolver: null, - - /** - Set this to provide an alternate class to `Ember.DefaultResolver` - - @property resolver - @public - */ - Resolver: null, - // This method must be moved to the application instance object willDestroy() { this._super(...arguments); @@ -1073,11 +1036,7 @@ Application.reopenClass({ @public */ buildRegistry(namespace) { - var registry = new Registry({ - resolver: resolverFor(namespace) - }); - - registry.set = set; + let registry = this._super(...arguments); registry.optionsForType('component', { singleton: false }); registry.optionsForType('view', { singleton: false }); @@ -1145,30 +1104,6 @@ Application.reopenClass({ } }); -/** - This function defines the default lookup rules for container lookups: - - * templates are looked up on `Ember.TEMPLATES` - * other names are looked up on the application after classifying the name. - For example, `controller:post` looks up `App.PostController` by default. - * if the default lookup fails, look for registered classes on the container - - This allows the application to register default injections in the container - that could be overridden by the normal naming convention. - - @private - @method resolverFor - @param {Ember.Namespace} namespace the namespace to look for classes - @return {*} the resolved value for a given lookup -*/ -function resolverFor(namespace) { - let ResolverClass = namespace.get('Resolver') || DefaultResolver; - - return ResolverClass.create({ - namespace: namespace - }); -} - function registerLibraries() { if (!librariesRegistered) { librariesRegistered = true; diff --git a/packages/ember-application/lib/system/engine.js b/packages/ember-application/lib/system/engine.js index ca37375df4d..2ec9118bb2b 100644 --- a/packages/ember-application/lib/system/engine.js +++ b/packages/ember-application/lib/system/engine.js @@ -3,12 +3,15 @@ @submodule ember-application */ import Namespace from 'ember-runtime/system/namespace'; +import Registry from 'container/registry'; import RegistryProxy from 'ember-runtime/mixins/registry_proxy'; import DAG from 'dag-map'; import { get } from 'ember-metal/property_get'; +import { set } from 'ember-metal/property_set'; import { assert, deprecate } from 'ember-metal/debug'; import { canInvoke } from 'ember-metal/utils'; import EmptyObject from 'ember-metal/empty_object'; +import DefaultResolver from 'ember-application/system/resolver'; function props(obj) { var properties = []; @@ -38,6 +41,25 @@ function props(obj) { @public */ let Engine = Namespace.extend(RegistryProxy, { + init() { + this._super(...arguments); + + this.buildRegistry(); + }, + + /** + Build and configure the registry for the current application. + + @private + @method buildRegistry + @return {Ember.Registry} the configured registry + */ + buildRegistry() { + var registry = this.__registry__ = this.constructor.buildRegistry(this); + + return registry; + }, + /** @private @method initializer @@ -293,9 +315,87 @@ Engine.reopenClass({ @param instanceInitializer @public */ - instanceInitializer: buildInitializerMethod('instanceInitializers', 'instance initializer') + instanceInitializer: buildInitializerMethod('instanceInitializers', 'instance initializer'), + + /** + This creates a registry with the default Ember naming conventions. + + It also configures the registry: + + * registered views are created every time they are looked up (they are + not singletons) + * registered templates are not factories; the registered value is + returned directly. + * the router receives the application as its `namespace` property + * all controllers receive the router as their `target` and `controllers` + properties + * all controllers receive the application as their `namespace` property + * the application view receives the application controller as its + `controller` property + * the application view receives the application template as its + `defaultTemplate` property + + @private + @method buildRegistry + @static + @param {Ember.Application} namespace the application for which to + build the registry + @return {Ember.Registry} the built registry + @public + */ + buildRegistry(namespace) { + var registry = new Registry({ + resolver: resolverFor(namespace) + }); + + registry.set = set; + + return registry; + }, + + /** + Set this to provide an alternate class to `Ember.DefaultResolver` + + + @deprecated Use 'Resolver' instead + @property resolver + @public + */ + resolver: null, + + /** + Set this to provide an alternate class to `Ember.DefaultResolver` + + @property resolver + @public + */ + Resolver: null }); +/** + This function defines the default lookup rules for container lookups: + + * templates are looked up on `Ember.TEMPLATES` + * other names are looked up on the application after classifying the name. + For example, `controller:post` looks up `App.PostController` by default. + * if the default lookup fails, look for registered classes on the container + + This allows the application to register default injections in the container + that could be overridden by the normal naming convention. + + @private + @method resolverFor + @param {Ember.Namespace} namespace the namespace to look for classes + @return {*} the resolved value for a given lookup +*/ +function resolverFor(namespace) { + let ResolverClass = namespace.get('Resolver') || DefaultResolver; + + return ResolverClass.create({ + namespace: namespace + }); +} + function buildInitializerMethod(bucketName, humanName) { return function(initializer) { // If this is the first initializer being added to a subclass, we are going to reopen the class From 9f0c63a5bdc07ede7b187f29ffda7323d7b65c80 Mon Sep 17 00:00:00 2001 From: Dan Gebhardt Date: Sat, 5 Dec 2015 10:20:45 -0500 Subject: [PATCH 04/10] [FEATURE ember-application-engines] Refactor container / registry initialization for engine instances. Move registry and container creation from `ApplicationInstance` to `EngineInstance`. --- .../lib/system/application-instance.js | 36 +------------ .../lib/system/application.js | 1 + .../lib/system/engine-instance.js | 52 ++++++++++++++++++- .../ember-application/lib/system/engine.js | 13 +++++ 4 files changed, 65 insertions(+), 37 deletions(-) diff --git a/packages/ember-application/lib/system/application-instance.js b/packages/ember-application/lib/system/application-instance.js index a5d2dfcff7f..b64637f36d5 100644 --- a/packages/ember-application/lib/system/application-instance.js +++ b/packages/ember-application/lib/system/application-instance.js @@ -10,7 +10,6 @@ import { set } from 'ember-metal/property_set'; import run from 'ember-metal/run_loop'; import { computed } from 'ember-metal/computed'; import DOMHelper from 'ember-htmlbars/system/dom-helper'; -import Registry from 'container/registry'; import { buildFakeRegistryWithDeprecations } from 'ember-runtime/mixins/registry_proxy'; import Renderer from 'ember-metal-views/renderer'; import assign from 'ember-metal/assign'; @@ -82,22 +81,12 @@ let ApplicationInstance = EngineInstance.extend({ init() { this._super(...arguments); - var application = get(this, 'application'); + let application = get(this, 'application'); if (!isEnabled('ember-application-visit')) { set(this, 'rootElement', get(application, 'rootElement')); } - // Create a per-instance registry that will use the application's registry - // as a fallback for resolving registrations. - var applicationRegistry = get(application, '__registry__'); - var registry = this.__registry__ = new Registry({ - fallback: applicationRegistry - }); - - // Create a per-instance container from the instance's registry - this.__container__ = registry.container({ owner: this }); - // Register this instance in the per-instance registry. // // Why do we need to register the instance in the first place? @@ -267,29 +256,6 @@ let ApplicationInstance = EngineInstance.extend({ dispatcher.setup(customEvents, this.rootElement); return dispatcher; - }, - - /** - @private - */ - willDestroy() { - this._super(...arguments); - run(this.__container__, 'destroy'); - }, - - /** - Unregister a factory. - - Overrides `RegistryProxy#unregister` in order to clear any cached instances - of the unregistered factory. - - @public - @method unregister - @param {String} fullName - */ - unregister(fullName) { - this.__container__.reset(fullName); - this._super(...arguments); } }); diff --git a/packages/ember-application/lib/system/application.js b/packages/ember-application/lib/system/application.js index 29bef8805cc..bc309fa2871 100644 --- a/packages/ember-application/lib/system/application.js +++ b/packages/ember-application/lib/system/application.js @@ -379,6 +379,7 @@ var Application = Engine.extend({ @return {Ember.ApplicationInstance} the application instance */ buildInstance(options = {}) { + options.base = this; options.application = this; return ApplicationInstance.create(options); }, diff --git a/packages/ember-application/lib/system/engine-instance.js b/packages/ember-application/lib/system/engine-instance.js index be8487d7bcd..36ce2f081ff 100644 --- a/packages/ember-application/lib/system/engine-instance.js +++ b/packages/ember-application/lib/system/engine-instance.js @@ -4,8 +4,12 @@ */ import EmberObject from 'ember-runtime/system/object'; +import Registry from 'container/registry'; import ContainerProxy from 'ember-runtime/mixins/container_proxy'; import RegistryProxy from 'ember-runtime/mixins/registry_proxy'; +import { get } from 'ember-metal/property_get'; +import { set } from 'ember-metal/property_set'; +import run from 'ember-metal/run_loop'; /** The `EngineInstance` encapsulates all of the stateful aspects of a @@ -20,12 +24,56 @@ import RegistryProxy from 'ember-runtime/mixins/registry_proxy'; let EngineInstance = EmberObject.extend(RegistryProxy, ContainerProxy, { /** - The `Engine` for which this is an instance. + The base `Engine` for which this is an instance. @property {Ember.Engine} engine @private */ - engine: null + base: null, + + init() { + this._super(...arguments); + + let base = get(this, 'base'); + + if (!base) { + base = get(this, 'application'); + set(this, 'base', base); + } + + // Create a per-instance registry that will use the application's registry + // as a fallback for resolving registrations. + let baseRegistry = get(base, '__registry__'); + let registry = this.__registry__ = new Registry({ + fallback: baseRegistry + }); + + // Create a per-instance container from the instance's registry + this.__container__ = registry.container({ owner: this }); + }, + + /** + Unregister a factory. + + Overrides `RegistryProxy#unregister` in order to clear any cached instances + of the unregistered factory. + + @public + @method unregister + @param {String} fullName + */ + unregister(fullName) { + this.__container__.reset(fullName); + this._super(...arguments); + }, + + /** + @private + */ + willDestroy() { + this._super(...arguments); + run(this.__container__, 'destroy'); + } }); export default EngineInstance; diff --git a/packages/ember-application/lib/system/engine.js b/packages/ember-application/lib/system/engine.js index 2ec9118bb2b..a39b56e891f 100644 --- a/packages/ember-application/lib/system/engine.js +++ b/packages/ember-application/lib/system/engine.js @@ -12,6 +12,7 @@ import { assert, deprecate } from 'ember-metal/debug'; import { canInvoke } from 'ember-metal/utils'; import EmptyObject from 'ember-metal/empty_object'; import DefaultResolver from 'ember-application/system/resolver'; +import EngineInstance from './engine-instance'; function props(obj) { var properties = []; @@ -47,6 +48,18 @@ let Engine = Namespace.extend(RegistryProxy, { this.buildRegistry(); }, + /** + Create an EngineInstance for this application. + + @private + @method buildInstance + @return {Ember.EngineInstance} the application instance + */ + buildInstance(options = {}) { + options.base = this; + return EngineInstance.create(options); + }, + /** Build and configure the registry for the current application. From 21e86e04291a60e984bae6d71c7ad0d1df9bae86 Mon Sep 17 00:00:00 2001 From: Dan Gebhardt Date: Sat, 5 Dec 2015 10:37:59 -0500 Subject: [PATCH 05/10] [FEATURE ember-application-engines] Feature flag for Ember.Engine. Only expose `Ember.Engine` when feature flag is enabled. --- features.json | 3 ++- packages/ember-application/lib/index.js | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/features.json b/features.json index 6f8832e0c4a..e6441405855 100644 --- a/features.json +++ b/features.json @@ -10,6 +10,7 @@ "ember-metal-ember-assign": null, "ember-contextual-components": true, "ember-container-inject-owner": true, - "ember-htmlbars-local-lookup": null + "ember-htmlbars-local-lookup": null, + "ember-application-engines": null } } diff --git a/packages/ember-application/lib/index.js b/packages/ember-application/lib/index.js index ba7379c31fe..00565174cc6 100644 --- a/packages/ember-application/lib/index.js +++ b/packages/ember-application/lib/index.js @@ -1,4 +1,5 @@ import Ember from 'ember-metal/core'; +import isEnabled from 'ember-metal/features'; import { runLoadHooks } from 'ember-runtime/system/lazy_load'; /** @@ -11,10 +12,14 @@ import { Resolver } from 'ember-application/system/resolver'; import Application from 'ember-application/system/application'; +import Engine from 'ember-application/system/engine'; Ember.Application = Application; Ember.Resolver = Resolver; Ember.DefaultResolver = DefaultResolver; +if (isEnabled('ember-application-engines')) { + Ember.Engine = Engine; +} runLoadHooks('Ember.Application', Application); From 2a4ead9c28ed149efa9f354e65eea4c401381289 Mon Sep 17 00:00:00 2001 From: Dan Gebhardt Date: Sat, 5 Dec 2015 11:03:20 -0500 Subject: [PATCH 06/10] [FEATURE ember-application-engines] Tests for engines. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replicate appropriate tests from applications. We don’t want to yet move tests while engines are feature flagged and in flux. --- .../tests/system/engine_test.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/ember-application/tests/system/engine_test.js b/packages/ember-application/tests/system/engine_test.js index ce55a17374b..903663318ad 100644 --- a/packages/ember-application/tests/system/engine_test.js +++ b/packages/ember-application/tests/system/engine_test.js @@ -1,12 +1,14 @@ +import Ember from 'ember-metal/core'; import run from 'ember-metal/run_loop'; import Engine from 'ember-application/system/engine'; +import EmberObject from 'ember-runtime/system/object'; -var engine; +let engine; QUnit.module('Ember.Engine', { setup() { run(function() { - engine = Engine.create({ router: null }); + engine = Engine.create(); }); }, @@ -16,3 +18,14 @@ QUnit.module('Ember.Engine', { } } }); + +QUnit.test('acts like a namespace', function() { + let lookup = Ember.lookup = {}; + + run(function() { + engine = lookup.TestEngine = Engine.create(); + }); + + engine.Foo = EmberObject.extend(); + equal(engine.Foo.toString(), 'TestEngine.Foo', 'Classes pick up their parent namespace'); +}); From c6dc2783ef6dff8010e17bb63d132731e822ff70 Mon Sep 17 00:00:00 2001 From: Dan Gebhardt Date: Sat, 5 Dec 2015 11:03:46 -0500 Subject: [PATCH 07/10] [FEATURE ember-application-engines] Tests for engine instances. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replicate appropriate tests from application instances. We don’t want to yet move tests while engines are feature flagged and in flux. --- .../tests/system/engine_instance_test.js | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/packages/ember-application/tests/system/engine_instance_test.js b/packages/ember-application/tests/system/engine_instance_test.js index 7e4ca9361ec..e8541ce4a61 100644 --- a/packages/ember-application/tests/system/engine_instance_test.js +++ b/packages/ember-application/tests/system/engine_instance_test.js @@ -1,5 +1,7 @@ import Engine from 'ember-application/system/engine'; +import EngineInstance from 'ember-application/system/engine-instance'; import run from 'ember-metal/run_loop'; +import factory from 'container/tests/test-helpers/factory'; let engine, engineInstance; @@ -20,3 +22,35 @@ QUnit.module('Ember.EngineInstance', { } } }); + +QUnit.test('an engine instance can be created based upon a base engine', function() { + run(function() { + engineInstance = EngineInstance.create({ base: engine }); + }); + + ok(engineInstance, 'instance should be created'); + equal(engineInstance.base, engine, 'base should be set to engine'); +}); + +QUnit.test('unregistering a factory clears all cached instances of that factory', function(assert) { + assert.expect(3); + + run(function() { + engineInstance = EngineInstance.create({ base: engine }); + }); + + let PostController = factory(); + + engineInstance.register('controller:post', PostController); + + let postController1 = engineInstance.lookup('controller:post'); + assert.ok(postController1, 'lookup creates instance'); + + engineInstance.unregister('controller:post'); + engineInstance.register('controller:post', PostController); + + let postController2 = engineInstance.lookup('controller:post'); + assert.ok(postController2, 'lookup creates instance'); + + assert.notStrictEqual(postController1, postController2, 'lookup creates a brand new instance, because previous one was reset'); +}); From c17979d6f00ef6d23587b2968872ee0bcf46d097 Mon Sep 17 00:00:00 2001 From: Dan Gebhardt Date: Sun, 6 Dec 2015 15:39:53 -0500 Subject: [PATCH 08/10] [FEATURE ember-application-engines] Use const for module-level declarations. --- packages/ember-application/lib/system/application-instance.js | 2 +- packages/ember-application/lib/system/application.js | 2 +- packages/ember-application/lib/system/engine-instance.js | 2 +- packages/ember-application/lib/system/engine.js | 2 +- packages/ember-application/lib/system/resolver.js | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/ember-application/lib/system/application-instance.js b/packages/ember-application/lib/system/application-instance.js index b64637f36d5..e0140f9c8b0 100644 --- a/packages/ember-application/lib/system/application-instance.js +++ b/packages/ember-application/lib/system/application-instance.js @@ -46,7 +46,7 @@ let BootOptions; @extends Ember.EngineInstance */ -let ApplicationInstance = EngineInstance.extend({ +const ApplicationInstance = EngineInstance.extend({ /** The `Application` for which this is an instance. diff --git a/packages/ember-application/lib/system/application.js b/packages/ember-application/lib/system/application.js index bc309fa2871..6db6e229496 100644 --- a/packages/ember-application/lib/system/application.js +++ b/packages/ember-application/lib/system/application.js @@ -196,7 +196,7 @@ var librariesRegistered = false; @public */ -var Application = Engine.extend({ +const Application = Engine.extend({ _suppressDeferredDeprecation: true, /** diff --git a/packages/ember-application/lib/system/engine-instance.js b/packages/ember-application/lib/system/engine-instance.js index 36ce2f081ff..a106b3540c7 100644 --- a/packages/ember-application/lib/system/engine-instance.js +++ b/packages/ember-application/lib/system/engine-instance.js @@ -22,7 +22,7 @@ import run from 'ember-metal/run_loop'; @uses ContainerProxyMixin */ -let EngineInstance = EmberObject.extend(RegistryProxy, ContainerProxy, { +const EngineInstance = EmberObject.extend(RegistryProxy, ContainerProxy, { /** The base `Engine` for which this is an instance. diff --git a/packages/ember-application/lib/system/engine.js b/packages/ember-application/lib/system/engine.js index a39b56e891f..f14386573e2 100644 --- a/packages/ember-application/lib/system/engine.js +++ b/packages/ember-application/lib/system/engine.js @@ -41,7 +41,7 @@ function props(obj) { @uses RegistryProxy @public */ -let Engine = Namespace.extend(RegistryProxy, { +const Engine = Namespace.extend(RegistryProxy, { init() { this._super(...arguments); diff --git a/packages/ember-application/lib/system/resolver.js b/packages/ember-application/lib/system/resolver.js index df40f8c5b12..99c99db071c 100644 --- a/packages/ember-application/lib/system/resolver.js +++ b/packages/ember-application/lib/system/resolver.js @@ -20,7 +20,7 @@ import { get as getTemplate } from 'ember-htmlbars/template_registry'; -export var Resolver = EmberObject.extend({ +export const Resolver = EmberObject.extend({ /* This will be set to the Application instance when it is created. From cb4a6748ee499dc9dda3a9688f0295725e00ea34 Mon Sep 17 00:00:00 2001 From: Dan Gebhardt Date: Sun, 6 Dec 2015 15:54:51 -0500 Subject: [PATCH 09/10] [FEATURE ember-application-engines] Remove unnecessary get/set calls. --- .../lib/system/application-instance.js | 2 +- .../ember-application/lib/system/engine-instance.js | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/ember-application/lib/system/application-instance.js b/packages/ember-application/lib/system/application-instance.js index e0140f9c8b0..45ae28331db 100644 --- a/packages/ember-application/lib/system/application-instance.js +++ b/packages/ember-application/lib/system/application-instance.js @@ -81,7 +81,7 @@ const ApplicationInstance = EngineInstance.extend({ init() { this._super(...arguments); - let application = get(this, 'application'); + let application = this.application; if (!isEnabled('ember-application-visit')) { set(this, 'rootElement', get(application, 'rootElement')); diff --git a/packages/ember-application/lib/system/engine-instance.js b/packages/ember-application/lib/system/engine-instance.js index a106b3540c7..6abedcc6e17 100644 --- a/packages/ember-application/lib/system/engine-instance.js +++ b/packages/ember-application/lib/system/engine-instance.js @@ -7,8 +7,6 @@ import EmberObject from 'ember-runtime/system/object'; import Registry from 'container/registry'; import ContainerProxy from 'ember-runtime/mixins/container_proxy'; import RegistryProxy from 'ember-runtime/mixins/registry_proxy'; -import { get } from 'ember-metal/property_get'; -import { set } from 'ember-metal/property_set'; import run from 'ember-metal/run_loop'; /** @@ -34,18 +32,17 @@ const EngineInstance = EmberObject.extend(RegistryProxy, ContainerProxy, { init() { this._super(...arguments); - let base = get(this, 'base'); + let base = this.base; if (!base) { - base = get(this, 'application'); - set(this, 'base', base); + base = this.application; + this.base = base; } // Create a per-instance registry that will use the application's registry // as a fallback for resolving registrations. - let baseRegistry = get(base, '__registry__'); let registry = this.__registry__ = new Registry({ - fallback: baseRegistry + fallback: base.__registry__ }); // Create a per-instance container from the instance's registry From 18b0a61d8c792f16afe5c15571978eff73ed3d26 Mon Sep 17 00:00:00 2001 From: Dan Gebhardt Date: Sun, 6 Dec 2015 17:39:17 -0500 Subject: [PATCH 10/10] [FEATURE ember-application-engines] Expose Ember.EngineInstance and Ember.ApplicationInstance. Expose Ember.EngineInstance and Ember.ApplicationInstance for easy overriding. Need to reanalyze whether to continue exposing them after feature flag is removed. --- packages/ember-application/lib/index.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/ember-application/lib/index.js b/packages/ember-application/lib/index.js index 00565174cc6..f76ad18b58e 100644 --- a/packages/ember-application/lib/index.js +++ b/packages/ember-application/lib/index.js @@ -12,7 +12,9 @@ import { Resolver } from 'ember-application/system/resolver'; import Application from 'ember-application/system/application'; +import ApplicationInstance from 'ember-application/system/application-instance'; import Engine from 'ember-application/system/engine'; +import EngineInstance from 'ember-application/system/engine-instance'; Ember.Application = Application; Ember.Resolver = Resolver; @@ -20,6 +22,11 @@ Ember.DefaultResolver = DefaultResolver; if (isEnabled('ember-application-engines')) { Ember.Engine = Engine; + + // Expose `EngineInstance` and `ApplicationInstance` for easy overriding. + // Reanalyze whether to continue exposing these after feature flag is removed. + Ember.EngineInstance = EngineInstance; + Ember.ApplicationInstance = ApplicationInstance; } runLoadHooks('Ember.Application', Application);