Skip to content

Commit

Permalink
Merge pull request #5212 from stefanpenner/faster-each-computed-property
Browse files Browse the repository at this point in the history
[Bugfix beta] dramatically improve performance of eachComputedProperty
  • Loading branch information
rwjblue committed Jul 24, 2014
2 parents 52baecd + e84f3e6 commit 8d9b0b3
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 9 deletions.
52 changes: 44 additions & 8 deletions packages/ember-runtime/lib/system/core_object.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ var applyMixin = Mixin._apply;
var finishPartial = Mixin.finishPartial;
var reopen = Mixin.prototype.reopen;
var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
var hasCachedComputedProperties = false;

var undefinedDescriptor = {
configurable: true,
Expand Down Expand Up @@ -746,6 +747,26 @@ var ClassMixin = Mixin.create({
return desc._meta || {};
},

_computedProperties: Ember.computed(function() {
hasCachedComputedProperties = true;
var proto = this.proto();
var descs = meta(proto).descs;
var property;
var properties = [];

for (var name in descs) {
property = descs[name];

if (property instanceof ComputedProperty) {
properties.push({
name: name,
meta: property._meta
});
}
}
return properties;
}).readOnly(),

/**
Iterate over each computed property for the class, passing its name
and any associated metadata (see `metaForProperty`) to the callback.
Expand All @@ -755,17 +776,15 @@ var ClassMixin = Mixin.create({
@param {Object} binding
*/
eachComputedProperty: function(callback, binding) {
var proto = this.proto();
var descs = meta(proto).descs;
var property, name;
var empty = {};
var property;

for (var name in descs) {
property = descs[name];
var properties = get(this, '_computedProperties');

if (property instanceof ComputedProperty) {
callback.call(binding || this, name, property._meta || empty);
}
for (var i = 0, length = properties.length; i < length; i++) {
property = properties[i];
name = property.name;
callback.call(binding || this, property.name, property.meta || empty);
}
}
});
Expand All @@ -777,6 +796,23 @@ if (Ember.config.overrideClassMixin) {
}

CoreObject.ClassMixin = ClassMixin;

ClassMixin.apply(CoreObject);

CoreObject.reopen({
didDefineProperty: function(proto, key, value) {
if (hasCachedComputedProperties === false) { return; }
if (value instanceof Ember.ComputedProperty) {
var cache = Ember.meta(this.constructor).cache;

if (cache._computedProperties !== undefined) {
cache._computedProperties = undefined;
}
}

this._super();
}
});


export default CoreObject;
36 changes: 35 additions & 1 deletion packages/ember-runtime/tests/system/object/computed_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ test("can retrieve metadata for a computed property", function() {
}, "metaForProperty() could not find a computed property with key 'staticProperty'.");
});

testBoth("can iterate over a list of computed properties for a class", function(get, set) {
test("can iterate over a list of computed properties for a class", function() {
var MyClass = EmberObject.extend({
foo: computed(function() {

Expand Down Expand Up @@ -204,3 +204,37 @@ testBoth("can iterate over a list of computed properties for a class", function(

deepEqual(list.sort(), ['bar', 'bat', 'baz', 'foo'], "all inherited properties are included");
});

test("list of properties updates when an additional property is added (such cache busting)", function() {
var MyClass = EmberObject.extend({
foo: computed(Ember.K),

fooDidChange: observer('foo', function() {

}),

bar: computed(Ember.K)
});

var list = [];

MyClass.eachComputedProperty(function(name) {
list.push(name);
});

deepEqual(list.sort(), ['bar', 'foo'].sort(), 'expected two computed properties');

MyClass.reopen({
baz: computed(Ember.K)
});

MyClass.create(); // force apply mixins

list = [];

MyClass.eachComputedProperty(function(name) {
list.push(name);
});

deepEqual(list.sort(), ['bar', 'foo', 'baz'].sort(), 'expected three computed properties');
});

0 comments on commit 8d9b0b3

Please sign in to comment.