Skip to content

Commit

Permalink
Merge pull request #10599 from emberjs/view-registry
Browse files Browse the repository at this point in the history
Don’t share view registry across containers
  • Loading branch information
mixonic committed Mar 10, 2015
2 parents a27163a + 6a71ff2 commit 069a243
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 10 deletions.
8 changes: 8 additions & 0 deletions packages/ember-application/lib/system/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,10 @@ var Application = Namespace.extend(DeferredMixin, {
buildDefaultInstance: function() {
var instance = this.buildInstance();

// For the default instance only, set the view registry to the global
// Ember.View.views hash for backwards-compatibility.
EmberView.views = instance.container.lookup('-view-registry:main');

// TODO2.0: Legacy support for App.__container__
// and global methods on App that rely on a single,
// default instance.
Expand Down Expand Up @@ -1006,6 +1010,10 @@ Application.reopenClass({
registry.register('view:select', SelectView);
registry.register('view:-outlet', OutletView);

registry.register('-view-registry:main', { create: function() { return {}; } });

registry.injection('view', '_viewRegistry', '-view-registry:main');

registry.register('view:default', _MetamorphView);
registry.register('view:toplevel', EmberView.extend());

Expand Down
42 changes: 42 additions & 0 deletions packages/ember-application/tests/system/visit_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import run from "ember-metal/run_loop";
import Application from "ember-application/system/application";
import ApplicationInstance from "ember-application/system/application-instance";
import Router from "ember-routing/system/router";
import View from "ember-views/views/view";
import compile from "ember-template-compiler/system/compile";

function createApplication() {
Expand Down Expand Up @@ -82,4 +83,45 @@ if (Ember.FEATURES.isEnabled('ember-application-visit')) {
assert.ok(false, "The visit() promise was rejected: " + error);
});
});

QUnit.test("Views created via visit() are not added to the global views hash", function(assert) {
QUnit.expect(6);
QUnit.stop();

var app;

run(function() {
app = createApplication();
app.instanceInitializer({
name: 'register-application-template',
initialize: function(app) {
app.registry.register('template:application', compile('<h1>Hello world</h1> {{view "child"}}'));
app.registry.register('view:application', View.extend({
elementId: 'my-cool-app'
}));
app.registry.register('view:child', View.extend({
elementId: 'child-view'
}));
}
});
});

assert.equal(Ember.$('#qunit-fixture').children().length, 0, "there are no elements in the fixture element");

app.visit('/').then(function(instance) {
QUnit.start();
assert.ok(instance instanceof ApplicationInstance, "promise is resolved with an ApplicationInstance");

run(instance.view, 'appendTo', '#qunit-fixture');
assert.equal(Ember.$("#qunit-fixture > #my-cool-app h1").text(), "Hello world", "the application was rendered once the promise resolves");
assert.strictEqual(View.views['my-cool-app'], undefined, "view was not registered globally");
ok(instance.container.lookup('-view-registry:main')['my-cool-app'] instanceof View, "view was registered on the instance's view registry");
ok(instance.container.lookup('-view-registry:main')['child-view'] instanceof View, "child view was registered on the instance's view registry");

instance.destroy();
}, function(error) {
QUnit.start();
assert.ok(false, "The visit() promise was rejected: " + error);
});
});
}
12 changes: 2 additions & 10 deletions packages/ember-views/lib/views/states/in_dom.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Ember from "ember-metal/core"; // Ember.assert
import create from 'ember-metal/platform/create';
import merge from "ember-metal/merge";
import EmberError from "ember-metal/error";
Expand All @@ -12,17 +11,12 @@ import hasElement from "ember-views/views/states/has_element";

var inDOM = create(hasElement);

var View;

merge(inDOM, {
enter: function(view) {
if (!View) { View = requireModule('ember-views/views/view')["default"]; } // ES6TODO: this sucks. Have to avoid cycles...

// Register the view for event handling. This hash is used by
// Ember.EventDispatcher to dispatch incoming events.
if (!view.isVirtual) {
Ember.assert("Attempted to register a view with an id already in use: "+view.elementId, !View.views[view.elementId]);
View.views[view.elementId] = view;
view._register();
}

Ember.runInDebug(function() {
Expand All @@ -33,10 +27,8 @@ merge(inDOM, {
},

exit: function(view) {
if (!View) { View = requireModule('ember-views/views/view')["default"]; } // ES6TODO: this sucks. Have to avoid cycles...

if (!this.isVirtual) {
delete View.views[view.elementId];
view._unregister();
}
},

Expand Down
31 changes: 31 additions & 0 deletions packages/ember-views/lib/views/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,10 @@ var View = CoreView.extend(
}

this._super.apply(this, arguments);

if (!this._viewRegistry) {
this._viewRegistry = View.views;
}
},

__defineNonEnumerable: function(property) {
Expand Down Expand Up @@ -1371,6 +1375,33 @@ var View = CoreView.extend(
return this.currentState.handleEvent(this, eventName, evt);
},

/**
Registers the view in the view registry, keyed on the view's `elementId`.
This is used by the EventDispatcher to locate the view in response to
events.
This method should only be called once the view has been inserted into the
DOM.
@method _register
@private
*/
_register: function() {
Ember.assert("Attempted to register a view with an id already in use: "+this.elementId, !this._viewRegistry[this.elementId]);
this._viewRegistry[this.elementId] = this;
},

/**
Removes the view from the view registry. This should be called when the
view is removed from DOM.
@method _unregister
@private
*/
_unregister: function() {
delete this._viewRegistry[this.elementId];
},

registerObserver: function(root, path, target, observer) {
if (!observer && 'function' === typeof target) {
observer = target;
Expand Down

0 comments on commit 069a243

Please sign in to comment.