diff --git a/packages/ember-htmlbars/lib/node-managers/component-node-manager.js b/packages/ember-htmlbars/lib/node-managers/component-node-manager.js
index d77265ed80d..d310293309c 100644
--- a/packages/ember-htmlbars/lib/node-managers/component-node-manager.js
+++ b/packages/ember-htmlbars/lib/node-managers/component-node-manager.js
@@ -300,16 +300,15 @@ ComponentNodeManager.prototype.destroy = function() {
export function createComponent(_component, isAngleBracket, _props, renderNode, env, attrs = {}, proto = _component.proto()) {
let props = assign({}, _props);
- let attrsSnapshot;
if (!isAngleBracket) {
let hasSuppliedController = 'controller' in attrs; // 2.0TODO remove
Ember.deprecate('controller= is deprecated', !hasSuppliedController, { id: 'ember-htmlbars.create-component', until: '3.0.0' });
- attrsSnapshot = takeSnapshot(attrs);
- props.attrs = attrsSnapshot;
+ let snapshot = takeSnapshot(attrs);
+ props.attrs = snapshot;
- mergeBindings(props, shadowedAttrs(proto, attrsSnapshot));
+ mergeBindings(props, shadowedAttrs(proto, snapshot));
} else {
props._isAngleBracket = true;
}
@@ -319,8 +318,6 @@ export function createComponent(_component, isAngleBracket, _props, renderNode,
let component = _component.create(props);
- env.renderer.componentInitAttrs(component, attrsSnapshot);
-
// for the fallback case
component.container = component.container || env.container;
diff --git a/packages/ember-htmlbars/lib/node-managers/view-node-manager.js b/packages/ember-htmlbars/lib/node-managers/view-node-manager.js
index 22d8d120684..00a0895b7ef 100644
--- a/packages/ember-htmlbars/lib/node-managers/view-node-manager.js
+++ b/packages/ember-htmlbars/lib/node-managers/view-node-manager.js
@@ -95,8 +95,6 @@ ViewNodeManager.prototype.render = function(env, attrs, visitor) {
}
if (component) {
- var snapshot = takeSnapshot(attrs);
- env.renderer.setAttrs(this.component, snapshot);
env.renderer.willRender(component);
env.renderedViews.push(component.elementId);
}
@@ -130,7 +128,7 @@ ViewNodeManager.prototype.rerender = function(env, attrs, visitor) {
env.renderer.willUpdate(component, snapshot);
if (component._renderNode.shouldReceiveAttrs) {
- env.renderer.updateAttrs(component, snapshot);
+ env.renderer.componentUpdateAttrs(component, snapshot);
setProperties(component, mergeBindings({}, shadowedAttrs(component, snapshot)));
component._renderNode.shouldReceiveAttrs = false;
}
@@ -187,6 +185,7 @@ export function createOrUpdateComponent(component, options, createOptions, rende
component = component.create(props);
} else {
+ env.renderer.componentUpdateAttrs(component, snapshot);
mergeBindings(props, shadowedAttrs(component, snapshot));
setProperties(component, props);
}
diff --git a/packages/ember-htmlbars/tests/integration/component_invocation_test.js b/packages/ember-htmlbars/tests/integration/component_invocation_test.js
index 3fe0e2bb387..7b1c95e29ca 100644
--- a/packages/ember-htmlbars/tests/integration/component_invocation_test.js
+++ b/packages/ember-htmlbars/tests/integration/component_invocation_test.js
@@ -810,55 +810,6 @@ QUnit.test('implementing `render` allows pushing into a string buffer', function
equal(view.$('#zomg').text(), 'Whoop!');
});
-QUnit.test('comopnent should rerender when a property is changed during children\'s rendering', function() {
- expectDeprecation(/twice in a single render/);
-
- var outer, middle;
-
- registry.register('component:x-outer', Component.extend({
- value: 1,
- grabReference: Ember.on('init', function() {
- outer = this;
- })
- }));
-
- registry.register('component:x-middle', Component.extend({
- grabReference: Ember.on('init', function() {
- middle = this;
- })
- }));
-
- registry.register('component:x-inner', Component.extend({
- pushDataUp: Ember.observer('value', function() {
- middle.set('value', this.get('value'));
- })
- }));
-
- registry.register('template:components/x-outer', compile('{{#x-middle}}{{x-inner value=value}}{{/x-middle}}'));
- registry.register('template:components/x-middle', compile('
{{value}}
{{yield}}'));
- registry.register('template:components/x-inner', compile('{{value}}
'));
-
-
- view = EmberView.extend({
- template: compile('{{x-outer}}'),
- container: container
- }).create();
-
- runAppend(view);
-
- equal(view.$('#inner-value').text(), '1', 'initial render of inner');
- equal(view.$('#middle-value').text(), '1', 'initial render of middle');
-
- run(() => outer.set('value', 2));
-
- equal(view.$('#inner-value').text(), '2', 'second render of inner');
- equal(view.$('#middle-value').text(), '2', 'second render of middle');
-
- run(() => outer.set('value', 3));
-
- equal(view.$('#inner-value').text(), '3', 'third render of inner');
- equal(view.$('#middle-value').text(), '3', 'third render of middle');
-});
QUnit.test('components in template of a yielding component should have the proper parentView', function() {
var outer, innerTemplate, innerLayout;
@@ -970,7 +921,7 @@ QUnit.test('components should receive the viewRegistry from the parent view', fu
equal(outer._viewRegistry, viewRegistry);
});
-QUnit.test('comopnent should rerender when a property (with a default) is changed during children\'s rendering', function() {
+QUnit.test('comopnent should rerender when a property is changed during children\'s rendering', function() {
expectDeprecation(/modified value twice in a single render/);
var outer, middle;
diff --git a/packages/ember-views/lib/compat/attrs-proxy.js b/packages/ember-views/lib/compat/attrs-proxy.js
index 7711eb79283..c20ee49911c 100644
--- a/packages/ember-views/lib/compat/attrs-proxy.js
+++ b/packages/ember-views/lib/compat/attrs-proxy.js
@@ -1,15 +1,7 @@
-import { get } from 'ember-metal/property_get';
import { Mixin } from 'ember-metal/mixin';
-import { on } from 'ember-metal/events';
import { symbol } from 'ember-metal/utils';
import { PROPERTY_DID_CHANGE } from 'ember-metal/property_events';
-
-import {
- addObserver,
- removeObserver,
- _addBeforeObserver,
- _removeBeforeObserver
-} from 'ember-metal/observer';
+import { on } from 'ember-metal/events';
export function deprecation(key) {
return `You tried to look up an attribute directly on the component. This is deprecated. Use attrs.${key} instead.`;
@@ -21,16 +13,6 @@ function isCell(val) {
return val && val[MUTABLE_CELL];
}
-function attrsWillChange(view, attrsKey) {
- let key = attrsKey.slice(6);
- view.currentState.legacyAttrWillChange(view, key);
-}
-
-function attrsDidChange(view, attrsKey) {
- let key = attrsKey.slice(6);
- view.currentState.legacyAttrDidChange(view, key);
-}
-
let AttrsProxyMixin = {
attrs: null,
@@ -56,46 +38,39 @@ let AttrsProxyMixin = {
val.update(value);
},
- willWatchProperty(key) {
- if (this._isAngleBracket || key === 'attrs') { return; }
-
- let attrsKey = `attrs.${key}`;
- _addBeforeObserver(this, attrsKey, null, attrsWillChange);
- addObserver(this, attrsKey, null, attrsDidChange);
+ _propagateAttrsToThis() {
+ let attrs = this.attrs;
+ let values = {};
+ for (let prop in attrs) {
+ if (prop !== 'attrs') {
+ values[prop] = this.getAttr(prop);
+ }
+ }
+ this.setProperties(values);
},
- didUnwatchProperty(key) {
- if (this._isAngleBracket || key === 'attrs') { return; }
+ initializeShape: on('init', function() {
+ this._isDispatchingAttrs = false;
+ }),
- let attrsKey = `attrs.${key}`;
- _removeBeforeObserver(this, attrsKey, null, attrsWillChange);
- removeObserver(this, attrsKey, null, attrsDidChange);
+ didReceiveAttrs() {
+ this._super();
+ this._isDispatchingAttrs = true;
+ this._propagateAttrsToThis();
+ this._isDispatchingAttrs = false;
},
- legacyDidReceiveAttrs: on('didReceiveAttrs', function() {
- if (this._isAngleBracket) { return; }
-
- var keys = Object.keys(this.attrs);
-
- for (var i = 0, l = keys.length; i < l; i++) {
- // Only issue the deprecation if it wasn't already issued when
- // setting attributes initially.
- if (!(keys[i] in this)) {
- this.notifyPropertyChange(keys[i]);
- }
- }
- }),
unknownProperty(key) {
if (this._isAngleBracket) { return; }
- var attrs = get(this, 'attrs');
+ var attrs = this.attrs;
if (attrs && key in attrs) {
// do not deprecate accessing `this[key]` at this time.
// add this back when we have a proper migration path
// Ember.deprecate(deprecation(key), { id: 'ember-views.', until: '3.0.0' });
- let possibleCell = get(attrs, key);
+ let possibleCell = attrs.key;
if (possibleCell && possibleCell[MUTABLE_CELL]) {
return possibleCell.value;
@@ -112,6 +87,7 @@ let AttrsProxyMixin = {
AttrsProxyMixin[PROPERTY_DID_CHANGE] = function(key) {
if (this._isAngleBracket) { return; }
+ if (this._isDispatchingAttrs) { return; }
if (this.currentState) {
this.currentState.legacyPropertyDidChange(this, key);
diff --git a/packages/ember-views/lib/views/states/default.js b/packages/ember-views/lib/views/states/default.js
index b19b118e417..6a496d4ab16 100644
--- a/packages/ember-views/lib/views/states/default.js
+++ b/packages/ember-views/lib/views/states/default.js
@@ -1,11 +1,5 @@
import EmberError from 'ember-metal/error';
import { get } from 'ember-metal/property_get';
-
-import {
- propertyWillChange,
- propertyDidChange
-} from 'ember-metal/property_events';
-
import { MUTABLE_CELL } from 'ember-views/compat/attrs-proxy';
/**
@@ -26,21 +20,8 @@ export default {
return null;
},
- legacyAttrWillChange(view, key) {
- if (key in view.attrs && !(key in view)) {
- propertyWillChange(view, key);
- }
- },
-
- legacyAttrDidChange(view, key) {
- if (key in view.attrs && !(key in view)) {
- propertyDidChange(view, key);
- }
- },
-
legacyPropertyDidChange(view, key) {
let attrs = view.attrs;
-
if (attrs && key in attrs) {
let possibleCell = attrs[key];
diff --git a/packages/ember-views/lib/views/states/pre_render.js b/packages/ember-views/lib/views/states/pre_render.js
index 0f26d12a541..67feef5002d 100644
--- a/packages/ember-views/lib/views/states/pre_render.js
+++ b/packages/ember-views/lib/views/states/pre_render.js
@@ -9,8 +9,6 @@ import merge from 'ember-metal/merge';
let preRender = Object.create(_default);
merge(preRender, {
- legacyAttrWillChange(view, key) {},
- legacyAttrDidChange(view, key) {},
legacyPropertyDidChange(view, key) {}
});
diff --git a/packages/ember-views/lib/views/view.js b/packages/ember-views/lib/views/view.js
index 14f4cea0698..573a94a7cfa 100644
--- a/packages/ember-views/lib/views/view.js
+++ b/packages/ember-views/lib/views/view.js
@@ -1322,6 +1322,8 @@ var View = CoreView.extend(
if (!this._viewRegistry) {
this._viewRegistry = View.views;
}
+
+ this.renderer.componentInitAttrs(this, this.attrs || {});
},
__defineNonEnumerable(property) {
diff --git a/packages/ember-views/tests/compat/attrs_proxy_test.js b/packages/ember-views/tests/compat/attrs_proxy_test.js
index c5cb269db02..01127f58447 100644
--- a/packages/ember-views/tests/compat/attrs_proxy_test.js
+++ b/packages/ember-views/tests/compat/attrs_proxy_test.js
@@ -83,7 +83,6 @@ QUnit.test('an observer on an attribute in the root of the component is fired wh
barObserver: on('init', observer('bar', function() {
var count = get(this, 'observerFiredCount');
-
set(this, 'observerFiredCount', count + 1);
})),